A framework to assess the potential ecosystem service gains from restoration across five landscapes.

Purpose

Estimate the potential value of ecosystem services provision gain if the target surface is distributed randomly across the intervention areas.

The ecosystem data included here is derived from Chaplin-Kramer et. al (2022) Mapping the planet’s critical natural assets

  1. Coastal Protection. Unitless measure, refers to a vulnerability index. InVEST Coastal Vulnerability Model

  2. Nitrogen Export. Derived from the Nitrogen retention modeled using the InVEST Nutrient Delivery Ratio. Expressed in kg/pixel/year

  3. Sediment Retention. Derived using InVEST SDR: Sediment Delivery Ration. Values in ton/pixel/year

  4. Pollination. Derived from InVEST SDR: Pollinator Abundance Model. Units expressed on equivalent people feed. More information in Chaplin-Kramer, et al. 2022

  5. Nature Access represented as the number of people within 1 hour travel of natural and semi-natural lands (Chaplin-Kramer et al, 2022).

    Goals:

Methods:

Assumptions

  • All ecosystem services are equally valued.
  • Value is a constant function of service quantity.
  • Uniform likelihood of restoration across the intervention area unless constrained by inputs (e.g., masks, distance).
  • Independence of pixel values (no spatial autocorrelation considered in sampling)
  • Sampling provides a robust method for estimating random distribution effects.

Approach:

Combined ES raster production:

Preliminar first step to deal with raster data sets representing different variables.

Limitations: - Implicitly assumes equal importance of ecosystem services. - May overemphasize areas with one dominant service, especially pollination, which is contingent to agricultural production. - Fails to account for geographically weighted factors, plan to address.

Random Sampling:

Suited methodology when no location-based prioritization is assumed. Repeated sampling process assuming Central Limit Theorem. Summarize results with total estimated ES gains and confidence intervals.

1. Prepare Environemnt

Load libraries, functions and prepare template data

1.2 Load Templates

This loads and prepares template data used to align

# add backgrounds/templates to align 
path_lc <- here('ESA_LC') 
# load reclassified land cover map
tf <- file.path(path_lc, list.files(path_lc, pattern= "rec"))
lc <- lapply(tf,rast)
# create rcl matrix
rcl <- matrix(c(
  0, Inf, 0   # Any value greater than 0 becomes 1
), ncol = 3, byrow = TRUE)

#create background pixels, subsitute all by 0
tmp <- lapply(lc, function(r){
  r <- classify(r[[1]], rcl)
})

rm(lc)

2 Extract the data

2.1 List the Restoration Layers

#Restoration:
tiffes <- file.path(here("cropped_raster_data" ), list.files(paste0(here("cropped_raster_data")),pattern= '.tif$'))
#Remove points, risk reduction baselin    
tiffes <- tiffes[c(1:5,51:55,71:75,81:90,106:110)]
#tiffes <- tiffes[-c(6:10)]
#tiffes <- tiffes[c(6:10)]

2.2 Normalize and combine data layers

The combined raster is a proxy for the total ES provided(with some assumptions that need to be eventually reviewed and refined).

2.3 Load Adjusted Griscom Restoration Data and apply mask

Use the adjusted Griscom restoration data (deals with pixel values encoding issues in the original data, had to get the metadadata for that). We apply this mask to isolate only the pixels that have been identified as Restoration Potential in Griscom’s Dataset on Global priority areas for ecosystem restoration.

Intervention Areas & Combiend Restoration Potential
Intervention Areas & Combiend Restoration Potential

3 Calculate Restoration Potential output.

tiffes <- file.path(here("restoration_combined"), list.files(paste0(here("restoration_combined")),pattern= 'ES_msk'))
baseES_m <- lapply(tiffes, rast)
tiffes
[1] "/home/jeronimo/OneDrive/WWF_nbs_op/restoration_combined/BRAZIL_ES_msk.tif"    
[2] "/home/jeronimo/OneDrive/WWF_nbs_op/restoration_combined/MADAGASCAR_ES_msk.tif"
[3] "/home/jeronimo/OneDrive/WWF_nbs_op/restoration_combined/MEXICO_ES_msk.tif"    
[4] "/home/jeronimo/OneDrive/WWF_nbs_op/restoration_combined/PERU_ES_msk.tif"      
[5] "/home/jeronimo/OneDrive/WWF_nbs_op/restoration_combined/VIETNAM_ES_msk.tif"   

3.1 Brazil Espiritu Santo

3.1.1 Prepare Template Brazil Espiritu Santo

This just create a background of Zeroes to use as template for reprojecting (this is necessary because the access layer whic is on a different crs. Not ideal, but need to move forward)

3.2 Madagascar (Not Necessary To Mask for te Interventions)

3.3 Yucatan

3.3.1 Prepare Template Yucatan

This just create a background of Zeroes to use as template for reprojecting (this is necessary because the access layer whic is on a different crs. Not ideal, but need to move forward)

3.3 Peru

3.4 Vietnam

Pending…

4 Sampling and Extracting values

This will be dealt on a two part basis: 1.Identify the hectares that yield the maximum aggregated restoration values withing the Griscom restoration potential pixels. Contingent on the entry assumptions 2. Model the estimated values of ES gains for the services based on a random sampling. This second part has implicit a couple of assumptions:

This approach utilizes a stratified random sampling technique to estimate the mean values of different bands in a multi-band raster dataset. Stratified random sampling is a probability sampling method where the population is divided into homogeneous subgroups called strata, and random samples are taken from each stratum. In this case, the strata are defined by the spatial extent of the raster dataset, and the pixels within the raster represent the individual sampling units.

Methodology

Define the Area of Interest: The first step is to define the area of interest (AOI) within the raster dataset. This AOI represents the spatial extent from which the samples will be drawn. In this specific case, the AOI is defined as 30,000 hectares.

Calculate the Sample Size: Based on the resolution of the raster and the desired AOI, the required number of pixels to be sampled is calculated. This ensures that the total area covered by the sampled pixels corresponds to the defined AOI.

Perform Stratified Random Sampling: The spatSample() function from the terra package in R is used to perform stratified random sampling. This function allows for random sampling of pixels within the defined AOI, while also excluding pixels with “NA” values in all bands, ensuring that only valid data points are included in the analysis.

Repeat Sampling: To reduce potential sampling bias and improve the accuracy of the estimates, the random sampling process is repeated multiple times (in this case, 30 times). This is analogous to the concept of bootstrapping, where repeated sampling with replacement is used to estimate the sampling distribution of a statistic.

Calculate Summary Statistics: For each repetition, the mean, standard deviation, and 95% confidence intervals are calculated for each band in the raster dataset. This provides a measure of the central tendency and variability of the sampled data.

Synthesize Results: The results from all repetitions are combined to calculate an overall mean and confidence interval for each band. This provides a more robust estimate of the expected values, effectively correcting for potential outliers and reducing the influence of individual sample variations.

Theoretical Justification

The use of stratified random sampling is justified as it ensures that the sample is representative of the entire population (i.e., all pixels within the AOI). By dividing the population into strata and sampling from each stratum, this method reduces the variability of the estimates compared to simple random sampling. This is particularly important when dealing with spatial data, where there may be inherent spatial autocorrelation or heterogeneity.

The repeated sampling approach further enhances the robustness of the estimates by providing a distribution of possible values. This allows for the calculation of confidence intervals, which provide a measure of the uncertainty associated with the estimates. By synthesizing the results from multiple repetitions, the overall estimates are less susceptible to the influence of individual sample variations and provide a more accurate representation of the true population values.

References

Cochran, W. G. (1977). Sampling techniques (3rd ed.). John Wiley & Sons. Lohr, S. L. (2010). Sampling: Design and analysis (2nd ed.). Brooks/Cole. 1
1. Bivand, R. S., Pebesma, E. J., & Gómez-Rubio, V. (2013). Applied spatial data analysis with R (2nd ed.). Springer.

4.1 Espirito Santo

4.1.1 Prepare Data Esp Santo.

Align and resampe all the raster datasets to the same crs and origin.

4.1.2 Run Sampling and Syntetize results - Espirito Santo

Here, we are sampling the data for obtain estimate of the expected restoration gains assuming randomly selected pixels extracted form the potential restoration areas. Again, some assumptions will have to be reviewed, but this is an initial assessment. The targeted intervention area is 30.200 ha.

4.1.3 Plot Results Espirito Santo

4.2 Yucatan

The approach is the same as in Brazil. Two main intervention areas were used tro build the final polygon: the jaguar corridor and ### 4.2.1 Prepare Data Yucatan. Align and resample all the raster bands to the ame crs and origin.

4.1.2 Run Sampling and Synthetize results - Yucatan

4.1.3 . Plot Results Yucatan

Next Steps:

Run the Analysis for Madre de Dios, incorpporate beneficiaries/population related data, as the target metric is not the sum of the values.

LS0tCnRpdGxlOiAiRGFUYSBQcmVwYXJhdGlvbiBOQlMiCm91dHB1dDoKICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQKICBodG1sX2RvY3VtZW50OgogICAgZGZfcHJpbnQ6IHBhZ2VkCmVkaXRvcl9vcHRpb25zOgogIG1hcmtkb3duOgogICAgd3JhcDogNzIKLS0tCgoKCkEgZnJhbWV3b3JrIHRvIGFzc2VzcyB0aGUgcG90ZW50aWFsIGVjb3N5c3RlbSBzZXJ2aWNlIGdhaW5zIGZyb20gcmVzdG9yYXRpb24gYWNyb3NzIGZpdmUgbGFuZHNjYXBlcy4KCiMgUHVycG9zZQoKRXN0aW1hdGUgdGhlIHBvdGVudGlhbCB2YWx1ZSBvZiBlY29zeXN0ZW0gc2VydmljZXMgcHJvdmlzaW9uIGdhaW4gIGlmIHRoZSB0YXJnZXQgc3VyZmFjZSBpcyBkaXN0cmlidXRlZCByYW5kb21seSBhY3Jvc3MgdGhlIGludGVydmVudGlvbiBhcmVhcy4KCgpUaGUgZWNvc3lzdGVtIGRhdGEgaW5jbHVkZWQgaGVyZSBpcyBkZXJpdmVkIGZyb20gQ2hhcGxpbi1LcmFtZXIgZXQuIGFsICgyMDIyKSBbKipNYXBwaW5nIHRoZSBwbGFuZXTigJlzIGNyaXRpY2FsIG5hdHVyYWwgYXNzZXRzKipdKGh0dHBzOi8vd3d3Lm5hdHVyZS5jb20vYXJ0aWNsZXMvczQxNTU5LTAyMi0wMTkzNC01KQoKCjEuIENvYXN0YWwgUHJvdGVjdGlvbi4gVW5pdGxlc3MgbWVhc3VyZSwgcmVmZXJzIHRvIGEgdnVsbmVyYWJpbGl0eSBpbmRleC4gWyoqSW5WRVNUIENvYXN0YWwgVnVsbmVyYWJpbGl0eSBNb2RlbCoqXShodHRwczovL3N0b3JhZ2UuZ29vZ2xlYXBpcy5jb20vcmVsZWFzZXMubmF0dXJhbGNhcGl0YWxwcm9qZWN0Lm9yZy9pbnZlc3QtdXNlcmd1aWRlL2xhdGVzdC9lbi9jb2FzdGFsX3Z1bG5lcmFiaWxpdHkuaHRtbCkKCjIuIE5pdHJvZ2VuIEV4cG9ydC4gRGVyaXZlZCBmcm9tIHRoZSBOaXRyb2dlbiByZXRlbnRpb24gbW9kZWxlZCB1c2luZyB0aGUgWyoqSW5WRVNUIE51dHJpZW50IERlbGl2ZXJ5IFJhdGlvKipdKGh0dHA6Ly9kYXRhLm5hdHVyYWxjYXBpdGFscHJvamVjdC5vcmcvaW52ZXN0LXJlbGVhc2VzLzMuNS4wL3VzZXJndWlkZS9uZHIuaHRtbCkuIEV4cHJlc3NlZCBpbiBrZy9waXhlbC95ZWFyCgozLiBTZWRpbWVudCBSZXRlbnRpb24uIERlcml2ZWQgdXNpbmcgWyoqSW5WRVNUIFNEUjogU2VkaW1lbnQgRGVsaXZlcnkgUmF0aW9uKipdKGh0dHBzOi8vc3RvcmFnZS5nb29nbGVhcGlzLmNvbS9yZWxlYXNlcy5uYXR1cmFsY2FwaXRhbHByb2plY3Qub3JnL2ludmVzdC11c2VyZ3VpZGUvbGF0ZXN0L2VuL3Nkci5odG1sKS4gVmFsdWVzIGluIHRvbi9waXhlbC95ZWFyCgo0LiBQb2xsaW5hdGlvbi4gRGVyaXZlZCBmcm9tIFsqKkluVkVTVCBTRFI6IFBvbGxpbmF0b3IgQWJ1bmRhbmNlIE1vZGVsKipdKGh0dHBzOi8vc3RvcmFnZS5nb29nbGVhcGlzLmNvbS9yZWxlYXNlcy5uYXR1cmFsY2FwaXRhbHByb2plY3Qub3JnL2ludmVzdC11c2VyZ3VpZGUvbGF0ZXN0L2VuL2Nyb3Bwb2xsaW5hdGlvbi5odG1sKS4gVW5pdHMgZXhwcmVzc2VkIG9uICplcXVpdmFsZW50IHBlb3BsZSBmZWVkKi4KIE1vcmUgaW5mb3JtYXRpb24gaW4gWyoqQ2hhcGxpbi1LcmFtZXIsIGV0IGFsLiAyMDIyKipdKGh0dHBzOi8vc3RhdGljLWNvbnRlbnQuc3ByaW5nZXIuY29tL2VzbS9hcnQlM0ExMC4xMDM4JTJGczQxNTU5LTAyMi0wMTkzNC01L01lZGlhT2JqZWN0cy80MTU1OV8yMDIyXzE5MzRfTU9FU00xX0VTTS5wZGYpCgo1LiBOYXR1cmUgQWNjZXNzIHJlcHJlc2VudGVkIGFzICp0aGUgbnVtYmVyIG9mIHBlb3BsZSB3aXRoaW4gMSBob3VyIHRyYXZlbCBvZiBuYXR1cmFsIGFuZCBzZW1pLW5hdHVyYWwgbGFuZHMqIChDaGFwbGluLUtyYW1lciBldCBhbCwgMjAyMikuCjogCiMgR29hbHM6CgotIElkZW50aWZ5IEhpZ2gtVmFsdWUgUGl4ZWxzOiBGb2N1cyByZXN0b3JhdGlvbiBvbiBhcmVhcyB3aGVyZSBlY29zeXN0ZW0gc2VydmljZSBnYWlucyBhcmUgbWF4aW1pemVkLgotIEVzdGltYXRlIFRvdGFsIEdhaW5zOiBJZiByZXN0b3JhdGlvbiBpcyBkaXN0cmlidXRlZCByYW5kb21seSBvdmVyIGEgdGFyZ2V0IGFyZWEsIHdoYXQgaXMgdGhlIGV4cGVjdGVkIGVjb3N5c3RlbSBzZXJ2aWNlIHZhbHVlPwoKLSBSZXByZXNlbnQgdW5jZXJ0YWludHkgdGhyb3VnaCBjb25maWRlbmNlIGludGVydmFscyBhbmQgc3BhdGlhbCBkaXN0cmlidXRpb25zIG9mIHNlbGVjdGVkIHBpeGVscy4KCiMgTWV0aG9kczoKCiMjIEFzc3VtcHRpb25zCgotIEFsbCBlY29zeXN0ZW0gc2VydmljZXMgYXJlIGVxdWFsbHkgdmFsdWVkLgotIFZhbHVlIGlzIGEgY29uc3RhbnQgZnVuY3Rpb24gb2Ygc2VydmljZSBxdWFudGl0eS4KLSBVbmlmb3JtIGxpa2VsaWhvb2Qgb2YgcmVzdG9yYXRpb24gYWNyb3NzIHRoZSBpbnRlcnZlbnRpb24gYXJlYSB1bmxlc3MgY29uc3RyYWluZWQgYnkgaW5wdXRzIChlLmcuLCBtYXNrcywgZGlzdGFuY2UpLgotIEluZGVwZW5kZW5jZSBvZiBwaXhlbCB2YWx1ZXMgKG5vIHNwYXRpYWwgYXV0b2NvcnJlbGF0aW9uIGNvbnNpZGVyZWQgaW4gc2FtcGxpbmcpCi0gU2FtcGxpbmcgcHJvdmlkZXMgYSByb2J1c3QgbWV0aG9kIGZvciBlc3RpbWF0aW5nIHJhbmRvbSBkaXN0cmlidXRpb24gZWZmZWN0cy4KCiMgQXBwcm9hY2g6CgotIE5vcm1hbGl6ZSBlY29zeXN0ZW0gc2VydmljZSByYXN0ZXJzIHRvIGEgMC0xIHNjYWxlLCBhZGQgdGhlbSwgYW5kIGlkZW50aWZ5IGhpZ2gtdmFsdWUgYXJlYXMuCi0gUmFuZG9tbHkgc2FtcGxlIHBpeGVscyB0byBlc3RpbWF0ZSBzZXJ2aWNlIHZhbHVlcyB1bmRlciByYW5kb20gZGlzdHJpYnV0aW9uIHNjZW5hcmlvcywgaXRlcmF0aW5nIG11bHRpcGxlIHRpbWVzIGZvciByb2J1c3QgY29uZmlkZW5jZSBpbnRlcnZhbHMuCi1BZGRyZXNzIHNwYXRpYWwgZGlzdHJpYnV0aW9uIGlzc3VlcyAoZS5nLiwgY2x1c3RlcmluZykgbGF0ZXIgdXNpbmcgYWRkaXRpb25hbCB3ZWlnaHRpbmcgZmFjdG9ycyAoZS5nLiwgZG93bnN0cmVhbSBiZW5lZmljaWFyaWVzKS4KCgojIyBDb21iaW5lZCBFUyByYXN0ZXIgcHJvZHVjdGlvbjoKClByZWxpbWluYXIgZmlyc3Qgc3RlcCB0byBkZWFsIHdpdGggcmFzdGVyIGRhdGEgc2V0cyByZXByZXNlbnRpbmcgZGlmZmVyZW50IHZhcmlhYmxlcy4KCioqTGltaXRhdGlvbnM6KioKLSBJbXBsaWNpdGx5IGFzc3VtZXMgZXF1YWwgaW1wb3J0YW5jZSBvZiBlY29zeXN0ZW0gc2VydmljZXMuCi0gTWF5IG92ZXJlbXBoYXNpemUgYXJlYXMgd2l0aCBvbmUgZG9taW5hbnQgc2VydmljZSwgZXNwZWNpYWxseSBwb2xsaW5hdGlvbiwgd2hpY2ggaXMgY29udGluZ2VudCB0byBhZ3JpY3VsdHVyYWwgcHJvZHVjdGlvbi4KLSBGYWlscyB0byBhY2NvdW50IGZvciBnZW9ncmFwaGljYWxseSB3ZWlnaHRlZCBmYWN0b3JzLCBwbGFuIHRvIGFkZHJlc3MuCgojIyBSYW5kb20gU2FtcGxpbmc6CgpTdWl0ZWQgbWV0aG9kb2xvZ3kgd2hlbiBubyBsb2NhdGlvbi1iYXNlZCBwcmlvcml0aXphdGlvbiBpcyBhc3N1bWVkLgpSZXBlYXRlZCAgc2FtcGxpbmcgcHJvY2VzcyAgYXNzdW1pbmcgIENlbnRyYWwgTGltaXQgVGhlb3JlbS4KU3VtbWFyaXplIHJlc3VsdHMgd2l0aCB0b3RhbCBlc3RpbWF0ZWQgRVMgZ2FpbnMgYW5kIGNvbmZpZGVuY2UgaW50ZXJ2YWxzLgoKCgojIDEuIFByZXBhcmUgRW52aXJvbmVtbnQgCgpMb2FkIGxpYnJhcmllcywgZnVuY3Rpb25zIGFuZCBwcmVwYXJlIHRlbXBsYXRlIGRhdGEgCgpgYGB7ciBhbGlnbiBsaXN0IG9mIHJhc3RlcnMsIGV2YWw9VFJVRSwgaW5jbHVkZT1GQUxTRX0KcGFja3MgPC0gYygndGVycmEnLCAncHVycnInLCAnbGFuZHNjYXBlbWV0cmljcycsICdzZicsJ2RwbHlyJywKICAgICAgICAgICAnaGVyZScsICdnZGFsVXRpbGl0aWVzJywgJ2pzb25saXRlJywgJ2RldnRvb2xzJywgJ3N0cmluZ3InLAogICAgICAgICAgICdwYXJhbGxlbCcsICdkcGx5cicsICd0aWR5cicsICdnZ3Bsb3QyJywgJ2phbml0b3InLCAnZm9yY2F0cycsICdmb3JlaWduJykKc2FwcGx5KHBhY2tzLCByZXF1aXJlLCBjaGFyYWN0ZXIub25seSA9IFRSVUUsIHF1aWV0bHk9VFJVRSkKcm0ocGFja3MpCmFsaWduX3Jhc3RlcnMgPC0gZnVuY3Rpb24ocmFzdGVyX2xpc3QsIHRlbXBsYXRlLCByZXNhbXBsZV9tZXRob2QgPSAiYmlsaW5lYXIiKSB7CiAgbGFwcGx5KHJhc3Rlcl9saXN0LCBmdW5jdGlvbihyKSB7CiAgICBpZiAoIWNvbXBhcmVHZW9tKHIsIHRlbXBsYXRlLCBzdG9wT25FcnJvciA9IEZBTFNFKSkgewogICAgICBtZXNzYWdlKCJBbGlnbmluZyByYXN0ZXI6ICIsIG5hbWVzKHIpKQogICAgICAjIFJlc2FtcGxlIHRvIGFsaWduIHdpdGggdGhlIHRlbXBsYXRlCiAgICAgIHJlc2FtcGxlKHIsIHRlbXBsYXRlLCBtZXRob2QgPSByZXNhbXBsZV9tZXRob2QpCiAgICB9IGVsc2UgewogICAgICAjIFJldHVybiByYXN0ZXIgYXMgaXMgaWYgYWxyZWFkeSBhbGlnbmVkCiAgICAgIG1lc3NhZ2UoIlJhc3RlciBhbHJlYWR5IGFsaWduZWQ6ICIsIG5hbWVzKHIpKQogICAgICByCiAgICB9CiAgfSkKfQoKcHJvY2Vzc19yYXN0ZXJzIDwtIGZ1bmN0aW9uKG5lc3RlZF9saXN0LCB0ZW1wbGF0ZXMsIHJlc2FtcGxlX21ldGhvZCA9ICJiaWxpbmVhciIpIHsKICBsYXBwbHkoc2VxX2Fsb25nKG5lc3RlZF9saXN0KSwgZnVuY3Rpb24oaSkgewogICAgIyBBbGlnbiBhbGwgcmFzdGVycyBpbiB0aGUgc3VibGlzdCB0byB0aGUgdGVtcGxhdGUKICAgIGFsaWduZWQgPC0gbGFwcGx5KG5lc3RlZF9saXN0W1tpXV0sIGZ1bmN0aW9uKHIpIHsKICAgICAgaWYgKCFjb21wYXJlR2VvbShyLCB0ZW1wbGF0ZXNbW2ldXSwgc3RvcE9uRXJyb3IgPSBGQUxTRSkpIHsKICAgICAgICBtZXNzYWdlKCJBbGlnbmluZyByYXN0ZXI6ICIsIG5hbWVzKHIpKQogICAgICAgIHJlc2FtcGxlKHIsIHRlbXBsYXRlc1tbaV1dLCBtZXRob2QgPSByZXNhbXBsZV9tZXRob2QpCiAgICAgIH0gZWxzZSB7CiAgICAgICAgbWVzc2FnZSgiUmFzdGVyIGFscmVhZHkgYWxpZ25lZDogIiwgbmFtZXMocikpCiAgICAgICAgcgogICAgICB9CiAgICB9KQogICAgIyBTdGFjayBhbGwgYWxpZ25lZCByYXN0ZXJzIGludG8gYSBzaW5nbGUgbXVsdGliYW5kIFNwYXRSYXN0ZXIKICAgIHN0YWNrZWQgPC0gZG8uY2FsbChjLCBhbGlnbmVkKQogICAgCiAgIHRtcCAjIE1lcmdlIHRoZSBzdGFja2VkIHJhc3RlciB3aXRoIHRoZSBjb3JyZXNwb25kaW5nIHRlbXBsYXRlIHJhc3RlcgogICAgbWVyZ2VkIDwtIG1lcmdlKHN0YWNrZWQsIHRlbXBsYXRlc1tbaV1dKQogICAgCiAgICAjIFN1bSB0aGUgbGF5ZXJzIG9mIHRoZSBtZXJnZWQgcmFzdGVyCiAgICBhcHAobWVyZ2VkLCBzdW0pCiAgfSkKfQpub3JtYWxpemVfcmFzdGVyIDwtIGZ1bmN0aW9uKHIpIHsKICBtaW5fdmFsIDwtIG1pbih2YWx1ZXMociksIG5hLnJtID0gVFJVRSkKICBtYXhfdmFsIDwtIG1heCh2YWx1ZXMociksIG5hLnJtID0gVFJVRSkKICAociAtIG1pbl92YWwpIC8gKG1heF92YWwgLSBtaW5fdmFsKQp9Cgpwcm9jZXNzX2ludGVydmVudGlvbl9hcmVhIDwtIGZ1bmN0aW9uKHJhc3Rlcl9saXN0KSB7CiAgIyBOb3JtYWxpemUgZWFjaCByYXN0ZXIgaW4gdGhlIGxpc3QKICBub3JtYWxpemVkX3Jhc3RlcnMgPC0gbGFwcGx5KHJhc3Rlcl9saXN0LCBub3JtYWxpemVfcmFzdGVyKQogICMgQ29tYmluZSB0aGUgbm9ybWFsaXplZCByYXN0ZXJzIGJ5IHN1bW1pbmcgdGhlbQogIGNvbWJpbmVkX3Jhc3RlciA8LSBkby5jYWxsKHN1bSwgbm9ybWFsaXplZF9yYXN0ZXJzKQogIHJldHVybihjb21iaW5lZF9yYXN0ZXIpCn0KYGBgCgojIyAxLjIgTG9hZCBUZW1wbGF0ZXMKClRoaXMgbG9hZHMgYW5kIHByZXBhcmVzIHRlbXBsYXRlIGRhdGEgdXNlZCB0byBhbGlnbgpgYGB7ciBjcmVhdGUgdG1wfQpsaWJyYXJ5KGhlcmUpCiMgYWRkIGJhY2tncm91bmRzL3RlbXBsYXRlcyB0byBhbGlnbiAKcGF0aF9sYyA8LSBoZXJlKCdFU0FfTEMnKSAKIyBsb2FkIHJlY2xhc3NpZmllZCBsYW5kIGNvdmVyIG1hcAp0ZiA8LSBmaWxlLnBhdGgocGF0aF9sYywgbGlzdC5maWxlcyhwYXRoX2xjLCBwYXR0ZXJuPSAicmVjIikpCmxjIDwtIGxhcHBseSh0ZixyYXN0KQojIGNyZWF0ZSByY2wgbWF0cml4CnJjbCA8LSBtYXRyaXgoYygKICAwLCBJbmYsIDAgICAjIEFueSB2YWx1ZSBncmVhdGVyIHRoYW4gMCBiZWNvbWVzIDEKKSwgbmNvbCA9IDMsIGJ5cm93ID0gVFJVRSkKCiNjcmVhdGUgYmFja2dyb3VuZCBwaXhlbHMsIHN1YnNpdHV0ZSBhbGwgYnkgMAp0bXAgPC0gbGFwcGx5KGxjLCBmdW5jdGlvbihyKXsKICByIDwtIGNsYXNzaWZ5KHJbWzFdXSwgcmNsKQp9KQoKcm0obGMpCmBgYAoKCiMgMiBFeHRyYWN0IHRoZSBkYXRhCgojIyAyLjEgTGlzdCB0aGUgUmVzdG9yYXRpb24gTGF5ZXJzIApgYGB7ciBzZWxlY3QgY29uc2VydmF0aW9uIGRhdGF9CiNSZXN0b3JhdGlvbjoKdGlmZmVzIDwtIGZpbGUucGF0aChoZXJlKCJjcm9wcGVkX3Jhc3Rlcl9kYXRhIiApLCBsaXN0LmZpbGVzKHBhc3RlMChoZXJlKCJjcm9wcGVkX3Jhc3Rlcl9kYXRhIikpLHBhdHRlcm49ICcudGlmJCcpKQp0aWZmZXMgPC0gdGlmZmVzW2MoMTo1LDUxOjU1LDcxOjc1LDgxOjkwLDEwNjoxMTApXQpgYGAKCiMjIDIuMiBOb3JtYWxpemUgYW5kIGNvbWJpbmUgZGF0YSBsYXllcnMKClRoZSBjb21iaW5lZCByYXN0ZXIgaXMgYSBwcm94eSBmb3IgdGhlIHRvdGFsIEVTIHByb3ZpZGVkKHdpdGggc29tZSBhc3N1bXB0aW9ucyB0aGF0IG5lZWQgdG8gYmUgZXZlbnR1YWxseSByZXZpZXdlZCBhbmQgcmVmaW5lZCkuCgpgYGB7ciBhcHBseSBtYXNrIEFPSSBBUCwgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KCiMgU3RlcCAxOiBFeHRyYWN0IGZpbGUgbmFtZXMsIHByb2R1Y3QgbmFtZXMsIGFuZCBjb3VudHJ5IG5hbWVzCmZpbGVfbmFtZXMgPC0gYmFzZW5hbWUodGlmZmVzKSAgIyBFeHRyYWN0IGZpbGUgbmFtZXMgZnJvbSBwYXRocwoKIyBFeHRyYWN0IHByb2R1Y3QgbmFtZXMgYW5kIGNvdW50cnkgbmFtZXMKcHJvZHVjdF9uYW1lcyA8LSBzdWIoIl9bQS1aXStcXC50aWYkIiwgIiIsIGZpbGVfbmFtZXMpICAjIFJlbW92ZSAiX0NPVU5UUlkudGlmIiB0byBnZXQgcHJvZHVjdCBuYW1lCmNvdW50cnlfbmFtZXMgPC0gc3ViKCIuKl8oLio/KVxcLnRpZiQiLCAiXFwxIiwgZmlsZV9uYW1lcykgICMgRXh0cmFjdCBjb3VudHJ5IG5hbWUgZnJvbSBmaWxlIG5hbWUKCiMgU3RlcCAyOiBDcmVhdGUgYSBkYXRhZnJhbWUgdG8gb3JnYW5pemUgdGhlIGluZm9ybWF0aW9uCmZpbGVfaW5mbyA8LSBkYXRhLmZyYW1lKAogIEZpbGVQYXRoID0gdGlmZmVzLAogIFByb2R1Y3QgPSBwcm9kdWN0X25hbWVzLAogIENvdW50cnkgPSBjb3VudHJ5X25hbWVzLAogIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRQopCgojIFN0ZXAgMzogU29ydCB0aGUgZGF0YWZyYW1lIGJ5IENvdW50cnkgZmlyc3QsIHRoZW4gYnkgUHJvZHVjdApmaWxlX2luZm8gPC0gZmlsZV9pbmZvICU+JQogIGFycmFuZ2UoQ291bnRyeSwgUHJvZHVjdCkKCiMgU3RlcCA0OiBFeHRyYWN0IHRoZSBzb3J0ZWQgZmlsZSBwYXRocwp0aWZmZXMgPC0gZmlsZV9pbmZvJEZpbGVQYXRoCgpiYXNlRVMgPC0gbGFwcGx5KHRpZmZlcywgcmFzdCkKYmFzZUVTIDwtIGxhcHBseShiYXNlRVMsIGZ1bmN0aW9uKHIpewogIHIgPC0gbm9ybWFsaXplX3Jhc3RlcihyKQp9KQoKIyBzZXQgdGhlIG51bWJlciBvZiBkaWZmZXJlbnQgcHJvZHVjdHMgdG8gc3BsaXQgdGhlIGxpc3QgCm51bSA8LSBsZW5ndGgodW5pcXVlKHByb2R1Y3RfbmFtZXMpKQojIHNwbGl0IGFnYWluIHRvIGhhdmUgbmVzdGVkIGxpc3RzCmJhc2VFUyA8LSBzcGxpdChiYXNlRVMsIHJlcCgxOmxlbmd0aChuYW0pLCBlYWNoID0gbnVtKSkKCiMgYWxpZ24sIGFkZCBiYWNrZ3JvdW5kIGFuZCBzdW0gYWxsIHRoZSB2YWx1ZXMKYmFzZUVTIDwtIHByb2Nlc3NfcmFzdGVycyhiYXNlRVMsdG1wLCByZXNhbXBsZV9tZXRob2QgPSAiYmlsaW5lYXIiKQptYXAoMTpsZW5ndGgoYmFzZUVTKSwgZnVuY3Rpb24oeCkgd3JpdGVSYXN0ZXIoYmFzZUVTW1t4XV0sIHBhc3RlMChoZXJlKCJyZXN0b3JhdGlvbl9jb21iaW5lZCIpLCcvJywgdW5pcXVlKGNvdW50cnlfbmFtZXMpW1t4XV0sICdfRVNfc3VtLnRpZicpKSkKYGBgCgoKIyMgMi4zIExvYWQgQWRqdXN0ZWQgR3Jpc2NvbSBSZXN0b3JhdGlvbiBEYXRhIGFuZCBhcHBseSBtYXNrCgpVc2UgdGhlIGFkanVzdGVkIEdyaXNjb20gcmVzdG9yYXRpb24gZGF0YSAoZGVhbHMgd2l0aCBwaXhlbCB2YWx1ZXMgZW5jb2RpbmcgaXNzdWVzIGluIHRoZSBvcmlnaW5hbCBkYXRhLCBoYWQgdG8gZ2V0IHRoZSBtZXRhZGFkYXRhIGZvciB0aGF0KS4gV2UgYXBwbHkgdGhpcyBtYXNrIHRvIGlzb2xhdGUgb25seSB0aGUgcGl4ZWxzIHRoYXQgaGF2ZSBiZWVuIGlkZW50aWZpZWQgYXMgUmVzdG9yYXRpb24gUG90ZW50aWFsIGluIEdyaXNjb20ncyAgRGF0YXNldCBvbiBbR2xvYmFsIHByaW9yaXR5IGFyZWFzIGZvciBlY29zeXN0ZW0KcmVzdG9yYXRpb25dKGh0dHBzOi8vd3d3LmtzZmlyZS5vcmcvd29vZHlfZW5jcm9hY2htZW50L2RvY3VtZW50cy9HbG9iYWwlMjBwcmlvcml0eSUyMGFyZWFzJTIwb2YlMjBlY29zeXRlbSUyMHJlc3RvcmF0aW9uLnBkZikuCgoKCmBgYHtyIGxvYWQgR3Jpc2NvbXMgZGF0YSwgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KIyBMb2FkIEdyaXNjb20gRGF0YQp0aWZmZXMgPC0gZmlsZS5wYXRoKGhlcmUoIlJlc3RvcmF0aW9uX0dyaXNjb20iKSwgbGlzdC5maWxlcyhwYXN0ZTAoaGVyZSgiUmVzdG9yYXRpb25fR3Jpc2NvbSIpKSxwYXR0ZXJuPSAncmVjJykpCgpwYV9yYyA8LSBsYXBwbHkodGlmZmVzLHJhc3QpCgpiYXNlRVNfbSA8LSBtYXAyKAogIGJhc2VFUywgCiAgcGFfcmMsIAogIGZ1bmN0aW9uKHJzdCwgbXNrKSB7CiAgICAjIEFwcGx5IG1hc2sgdG8gZWFjaCByYXN0ZXIgaW4gdGhlIHN1Ymxpc3QgdXNpbmcgdGhlIGNvcnJlc3BvbmRpbmcgY291bnRyeSB2ZWN0b3IKICAgIG1hc2socnN0LCBtc2ssIG1hc2t2YWx1ZT0wKQogIH0KKQptYXAoMTpsZW5ndGgoYmFzZUVTKSwgZnVuY3Rpb24oeCkgd3JpdGVSYXN0ZXIoYmFzZUVTX21bW3hdXSwgcGFzdGUwKGhlcmUoInJlc3RvcmF0aW9uX2NvbWJpbmVkIiksJy8nLCB1bmlxdWUoY291bnRyeV9uYW1lcylbW3hdXSwgJ19FU19tc2sudGlmJyksIG92ZXJ3cml0ZT1UKSkKYGBgCgohW0ludGVydmVudGlvbiBBcmVhcyAmIENvbWJpZW5kIFJlc3RvcmF0aW9uIFBvdGVudGlhbF0oL2hvbWUvamVyb25pbW8vT25lRHJpdmUvV1dGX25ic19vcC9vdXRwdXRfbWFwcy9tYXBzX2ludGVydmVudGlvbnMucG5nKQoKCiMgMyBDYWxjdWxhdGUgUmVzdG9yYXRpb24gUG90ZW50aWFsIG91dHB1dC4KCgpgYGB7ciBsb2FkIGludGV2ZW50aW9uIGRhdGF9CnRpZmZlcyA8LSBmaWxlLnBhdGgoaGVyZSgicmVzdG9yYXRpb25fY29tYmluZWQiKSwgbGlzdC5maWxlcyhwYXN0ZTAoaGVyZSgicmVzdG9yYXRpb25fY29tYmluZWQiKSkscGF0dGVybj0gJ0VTX21zaycpKQpiYXNlRVNfbSA8LSBsYXBwbHkodGlmZmVzLCByYXN0KQp0aWZmZXMKYGBgCgojIyAzLjEgQnJhemlsIEVzcGlyaXR1IFNhbnRvCmBgYHtyIGJyYXppbCBpbnRlcnZlbnRpb24gLCBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQpwb2x5IDwtIHN0X3JlYWQoaGVyZSgiSW50ZXJ2ZW50aW9ucyIsICJCcmF6aWxfaW50X2FyZWFzIiwgIkVzcGlyaXRvX1NhbnRvX0FsYmVycy5zaHAiKSkKcG9sX3dncyA8LSBzdF90cmFuc2Zvcm0ocG9seSwgY3JzPWNycyhiYXNlRVNfbVtbMV1dKSkKc2Vydl9icmEgPC0gYmFzZUVTX21bWzFdXSAlPiUgY3JvcChwb2xfd2dzKSAlPiUgbWFzayhwb2xfd2dzKQpzZXJ2X2JyYSA8LSBwcm9qZWN0KHNlcnZfYnJhLCBjcnMocG9seSksIG1ldGhvZD0nY3ViaWMnKQpyZXN0X3NwIDwtIGNyb3AocGFfcmNbWzFdXSwgcG9sX3dncykKcmVzdF9zcCA8LSBtYXNrKHJlc3Rfc3AscG9sX3dncykKd3JpdGVSYXN0ZXIoc2Vydl9icmEsIGhlcmUoIkludGVydmVudGlvbnMiLCAiQnJhemlsX2ludGVydmVudGlvbiIsICJlc3Bfc2FudG9fcmVzdC50aWYiKSxvdmVyd3JpdGU9VFJVRSkKd3JpdGVSYXN0ZXIocmVzdF9zcCwgaGVyZSgiSW50ZXJ2ZW50aW9ucyIsICJCcmF6aWxfaW50ZXJ2ZW50aW9uIiwgIlNTX2dyaXNjb20udGlmIiksIG92ZXJ3cml0ZT1UUlVFKQoKYGBgCgojIyMgMy4xLjEgUHJlcGFyZSBUZW1wbGF0ZSBCcmF6aWwgRXNwaXJpdHUgU2FudG8KVGhpcyBqdXN0IGNyZWF0ZSBhIGJhY2tncm91bmQgb2YgWmVyb2VzIHRvIHVzZSBhcyB0ZW1wbGF0ZSBmb3IgcmVwcm9qZWN0aW5nICh0aGlzIGlzIG5lY2Vzc2FyeSBiZWNhdXNlIHRoZSBhY2Nlc3MgbGF5ZXIgd2hpYyBpcyBvbiBhIGRpZmZlcmVudCBjcnMuIE5vdCBpZGVhbCwgYnV0IG5lZWQgdG8gbW92ZSBmb3J3YXJkKQpgYGB7ciBicmF6aWwgaW50ZXJ2ZW50aW9uIDEsIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CnBvbHkgPC0gc3RfcmVhZChoZXJlKCJJbnRlcnZlbnRpb25zIiwgIkJyYXppbF9pbnRfYXJlYXMiLCAiRXNwaXJpdG9fU2FudG9fQWxiZXJzLnNocCIpKQpwb2xfd2dzIDwtIHN0X3RyYW5zZm9ybShwb2x5LCBjcnM9Y3JzKHRtcFtbMV1dKSkKc2Vydl9icmEgPC0gdG1wW1sxXV0gJT4lIGNyb3AocG9sX3dncykgJT4lIG1hc2socG9sX3dncykKc2Vydl9icmEgPC0gcHJvamVjdChzZXJ2X2JyYSwgY3JzKHBvbHkpLCByZXM9MzApCndyaXRlUmFzdGVyKHNlcnZfYnJhLCBoZXJlKCJJbnRlcnZlbnRpb25zIiwgIkJyYXppbF9pbnRlcnZlbnRpb24iLCAiZXNwX3NhbnRvX2JrZy50aWYiKSxvdmVyd3JpdGU9VFJVRSkKCmBgYAoKIyMgMy4yIE1hZGFnYXNjYXIgKE5vdCBOZWNlc3NhcnkgVG8gTWFzayBmb3IgdGUgSW50ZXJ2ZW50aW9ucykKYGBge3IgTWFkYWdhc2NhciBpbnRlcnZlbnRpb24gMSwgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KcG9seSA8LSBzdF9yZWFkKGhlcmUoIkludGVydmVudGlvbnMiLCAiTWV4X2ludGVydmVudGlvbiIsIm1leF9pbnRlcnZlbnRpb24yLmdlb2pzb24iKSkKCnBvbF93Z3MgPC0gc3RfdHJhbnNmb3JtKHBvbHksIGNycz1jcnMoYmFzZUVTX21bWzNdXSkpCnNlcnZfbWRnIDwtIGJhc2VFU19tW1szXV0gCnNlcnZfbWRnIDwtIHByb2plY3Qoc2Vydl9tZGcsIGNycyhwb2xfd2dzKSwgbWV0aG9kPSdjdWJpYycpCnJlc3RfbWRnIDwtIGNyb3AocGFfcmNbWzNdXSwgcG9sX3dncykKcmVzdF9zcCA8LSBtYXNrKHJlc3Rfc3AscG9sX3dncykKd3JpdGVSYXN0ZXIoc2Vydl9tZGcsIGhlcmUoIkludGVydmVudGlvbnMiLCAiTWRnX2ludGVydmVudGlvbiIsICJtZGdfaW50X3Jlc3QudGlmIikpCndyaXRlUmFzdGVyKHJlc3Rfc3AsIGhlcmUoIkludGVydmVudGlvbnMiLCAiTWRnX2ludGVydmVudGlvbiIsICJtZGdfZ3Jpc2NvbS50aWYiKSkKCmBgYAoKIyMgMy4zICBZdWNhdGFuCmBgYHtyIHl1Y2F0YW4gaW50ZXJ2ZW50aW9uIDEsIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CnBvbHkgPC0gc3RfcmVhZChoZXJlKCJJbnRlcnZlbnRpb25zIiwgIk1leF9pbnRlcnZlbnRpb24iLCJtZXhfaW50ZXJ2ZW50aW9uMi5nZW9qc29uIikpCgpwb2xfd2dzIDwtIHN0X3RyYW5zZm9ybShwb2x5LCBjcnM9Y3JzKGJhc2VFU19tW1szXV0pKQpzZXJ2X21leCA8LSBiYXNlRVNfbVtbM11dICU+JSBjcm9wKHBvbF93Z3MpICU+JSBtYXNrKHBvbF93Z3MpCnNlcnZfbWV4IDwtIHByb2plY3Qoc2Vydl9tZXgsIGNycyhwb2x5X3dncyksIG1ldGhvZD0nY3ViaWMnKQpyZXN0X21leCA8LSBjcm9wKHBhX3JjW1szXV0sIHBvbF93Z3MpCnJlc3RfbWV4IDwtIG1hc2socmVzdF9tZXgscG9sX3dncykKd3JpdGVSYXN0ZXIoc2Vydl9tZXgsIGhlcmUoIkludGVydmVudGlvbnMiLCAiTWV4X2ludGVydmVudGlvbiIsICJ5dWNhdGFuX2ludF9yZXN0LnRpZiIpKQp3cml0ZVJhc3RlcihyZXN0X21leCwgaGVyZSgiSW50ZXJ2ZW50aW9ucyIsICJNZXhfaW50ZXJ2ZW50aW9uIiwgIk1leF9ncmlzY29tLnRpZiIpLCBvdmVyd3JpdGU9VFJVRSkKCmBgYAoKIyMjIDMuMy4xIFByZXBhcmUgVGVtcGxhdGUgWXVjYXRhbgpUaGlzIGp1c3QgY3JlYXRlIGEgYmFja2dyb3VuZCBvZiBaZXJvZXMgdG8gdXNlIGFzIHRlbXBsYXRlIGZvciByZXByb2plY3RpbmcgKHRoaXMgaXMgbmVjZXNzYXJ5IGJlY2F1c2UgdGhlIGFjY2VzcyBsYXllciB3aGljIGlzIG9uIGEgZGlmZmVyZW50IGNycy4gTm90IGlkZWFsLCBidXQgbmVlZCB0byBtb3ZlIGZvcndhcmQpCmBgYHtyIGJyYXppbCBpbnRlcnZlbnRpb24sIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CnBvbHkgPC0gc3RfcmVhZChoZXJlKCJJbnRlcnZlbnRpb25zIiwgIk1leF9pbnRlcnZlbnRpb24iLCJtZXhfaW50ZXJ2ZW50aW9uMi5nZW9qc29uIikpCnBvbF93Z3MgPC0gc3RfdHJhbnNmb3JtKHBvbHksIGNycz1jcnModG1wW1szXV0pKQpzZXJ2X2JyYSA8LSB0bXBbWzNdXSAlPiUgY3JvcChwb2xfd2dzKSAlPiUgbWFzayhwb2xfd2dzKQpzZXJ2X2JyYSA8LSBwcm9qZWN0KHNlcnZfYnJhLCBjcnMocG9seSksIHJlcz0zMCkKd3JpdGVSYXN0ZXIoc2Vydl9icmEsIGhlcmUoIkludGVydmVudGlvbnMiLCAiTWV4X2ludGVydmVudGlvbiIsICJ5dWNhdGFuX2JrZy50aWYiKSxvdmVyd3JpdGU9VFJVRSkKCmBgYAojIyAzLjMgIFBlcnUKYGBge3IgTWFkcmUgRGUgRGlvcyBpbnRlcnZlbnRpb24sIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CnBvbCA8LSBzdF9yZWFkKGhlcmUoIkludGVydmVudGlvbnMiLCJQZXJ1IiwiSW50ZXJ2ZW5jaW9uZXMiLCAiY29tbW9uZGF0YSIsImdhbmFkZXJpYSIsIkdBTkFERVJJQS5zaHAiKSkKcG9sIDwtIHN0X21ha2VfdmFsaWQocG9sKQpzdF93cml0ZShwb2wsIGhlcmUoIkludGVydmVudGlvbnMiLCAiZ2FuYWRlcmlhLnNocCIpKQoKI2dldCBtc2sgbm9uIHplcm8gdmFsdWVzIGZyb20gdGhlIEVDIG1hc2sKbXNrX3AgPC0gY2xhc3NpZnkoYmFzZUVTW1s0XV0scmNsKQpwb2xfd2dzIDwtIHN0X3RyYW5zZm9ybShwb2wsIGNycz1jcnMoYmFzZUVTX21bWzRdXSkpCnNlcnZfcGVyX2dhbiA8LSBiYXNlRVNbWzRdXSAlPiUgY3JvcChwb2xfd2dzKSAlPiUgbWFzayhwb2xfd2dzKQoKcmVzdF9wZXIgPC0gcHJvamVjdChwYV9yY1tbNF1dLCBzZXJ2X3BlcikKcmVzdF9wZXIgPC0gY2xhc3NpZnkocmVzdF9wZXIscmNsKQpzZXJ2X3Blcl9nYW4gPC0gcHJvamVjdChzZXJ2X3Blcl9nYW4sIHNlcnZfcGVyLCBtZXRob2Q9J2JpbGluZWFyJykKbXNrX2cgPC0gY2xhc3NpZnkoc2Vydl9wZXJfZ2FuLHJjbCkgCm1za19nIDwtIHN1YnN0KG1za19nLCBmcm9tPTAsIHRvID0xKQpwZXIxIDwtIHByb2plY3QocGVyMSxzZXJ2X3BlcikKCm1hc2tfYWxsIDwtIG1lcmdlKG1za19nLHJlc3RfcGVyKQptYXNrX2FsbCA8LSBjbGFzc2lmeShtYXNrX2FsbCxyY2wpCm1ha3MgPC0gbGlzdChyZXN0X3BlciwgbXNrX2csIG1hc2tfYWxsKQoKbWFza19hbGxfd2dzIDwtIHByb2plY3QobWFza19hbGwsIGJhc2VFU1tbNF1dKQoKbWtzX3BlcnUgPC0gbWFzayhiYXNlRVNbWzRdXSxtYXNrX2FsbF93Z3MsIG1hc2t2YWx1ZT0wKQoKYXJlYXMgPC0gbGFwcGx5KG1ha3MsbHNtX2NfY2EpCnNhdmUoYXJlYXMsIGZpbGU9aGVyZSgiSW50ZXJ2ZW50aW9ucyIsICJQZXJ1X2ludGVydmVudGlvbiIsIlByb3BvcnRpb25zLlJEYXRhIikpCndyaXRlUmFzdGVyKG1hc2tfYWxsLCBoZXJlKCJJbnRlcnZlbnRpb25zIiwgIlBlcnVfaW50ZXJ2ZW50aW9uIiwiTUREbWFza19maW5hbC50aWYiKSwgb3ZlcndyaXRlPVRSVUUpCndyaXRlUmFzdGVyKG1rc19wZXJ1LCBoZXJlKCJJbnRlcnZlbnRpb25zIiwgIlBlcnVfaW50ZXJ2ZW50aW9uIiwiTURERUVTX2ZpbmFsLnRpZiIpLCBvdmVyd3JpdGU9VFJVRSkKCmBgYAoKIyMgMy40IFZpZXRuYW0KClBlbmRpbmcuLi4KCiMgNCBTYW1wbGluZyBhbmQgRXh0cmFjdGluZyB2YWx1ZXMKClRoaXMgd2lsbCBiZSBkZWFsdCBvbiBhIHR3byBwYXJ0IGJhc2lzOgoxLklkZW50aWZ5IHRoZSBoZWN0YXJlcyB0aGF0IHlpZWxkIHRoZSBtYXhpbXVtIGFnZ3JlZ2F0ZWQgcmVzdG9yYXRpb24gdmFsdWVzIHdpdGhpbmcgdGhlIEdyaXNjb20gcmVzdG9yYXRpb24gcG90ZW50aWFsIHBpeGVscy4gQ29udGluZ2VudCBvbiB0aGUgZW50cnkgYXNzdW1wdGlvbnMKMi4gTW9kZWwgdGhlIGVzdGltYXRlZCB2YWx1ZXMgb2YgRVMgZ2FpbnMgZm9yIHRoZSBzZXJ2aWNlcyBiYXNlZCBvbiBhIHJhbmRvbSBzYW1wbGluZy4KVGhpcyBzZWNvbmQgcGFydCBoYXMgaW1wbGljaXQgYSBjb3VwbGUgb2YgYXNzdW1wdGlvbnM6IAoKLSBXZSBhcmUgbm90IGNvbnNpZGVyaW5nIGFueSBzcGF0aWFsIGNvbmZpZ3VyYXRpb24gKGxhbmRzY2FwZSBtZXRyaWNzKSBhc3BlY3RzIGFmZmVjdGluZyB0aGUgdG90YWwgdmFsdWUKLSBFdmVudHVhbGx5LCB0aGUgbW9kZWwgY2FuIGJlIHJlZmluZWQgYnkgaW5jb3Jwb3JhdGluZyBhZGRpdGlvbmFsIHBhcmFtZXRlcnMgKGUuZyBtaW5pbXVtIGRpc3RhbmNlIHRvIGJvdW5kYXJpZXMsIGRpc3RhbmNlIGJldHdlZW4gcG9pbnRzLCB0b3BvZ3JhcGh5IG9yIGluaGFiaXRlZCBhcmVhcyAoc29tZSBvZiBpdCBpcyBpbXBsaWNpdCBpbiB0aGUgaW5wdXQgZGF0YSwgYnV0IG5lZWRzIHRvIGJlIGNvbmZpcm1lZCkuCi0gQ29hc3RhbCByaXNrIHByb3RlY3Rpb24gb25seSBvY2N1cnMgYXQgdGhlIGNvYXN0LCBhbnkgcmFuZG9tIHNhbXBsaW5nIHBlcmZvcm1lZCB3aWxsIGhhdmV0byBjb25zaWRlciB0aGlzLiBUaGlzIGNhbiBiZSBhZGp1c3RlZCB1c2luZyB3ZWlnaHRzLgoKClRoaXMgYXBwcm9hY2ggdXRpbGl6ZXMgYSBzdHJhdGlmaWVkIHJhbmRvbSBzYW1wbGluZyB0ZWNobmlxdWUgdG8gZXN0aW1hdGUgdGhlIG1lYW4gdmFsdWVzIG9mIGRpZmZlcmVudCBiYW5kcyBpbiBhIG11bHRpLWJhbmQgcmFzdGVyIGRhdGFzZXQuIFN0cmF0aWZpZWQgcmFuZG9tIHNhbXBsaW5nIGlzIGEgcHJvYmFiaWxpdHkgc2FtcGxpbmcgbWV0aG9kIHdoZXJlIHRoZSBwb3B1bGF0aW9uIGlzIGRpdmlkZWQgaW50byBob21vZ2VuZW91cyBzdWJncm91cHMgY2FsbGVkIHN0cmF0YSwgYW5kIHJhbmRvbSBzYW1wbGVzIGFyZSB0YWtlbiBmcm9tIGVhY2ggc3RyYXR1bS4gSW4gdGhpcyBjYXNlLCB0aGUgc3RyYXRhIGFyZSBkZWZpbmVkIGJ5IHRoZSBzcGF0aWFsIGV4dGVudCBvZiB0aGUgcmFzdGVyIGRhdGFzZXQsIGFuZCB0aGUgcGl4ZWxzIHdpdGhpbiB0aGUgcmFzdGVyIHJlcHJlc2VudCB0aGUgaW5kaXZpZHVhbCBzYW1wbGluZyB1bml0cy4KCk1ldGhvZG9sb2d5CgpEZWZpbmUgdGhlIEFyZWEgb2YgSW50ZXJlc3Q6IFRoZSBmaXJzdCBzdGVwIGlzIHRvIGRlZmluZSB0aGUgYXJlYSBvZiBpbnRlcmVzdCAoQU9JKSB3aXRoaW4gdGhlIHJhc3RlciBkYXRhc2V0LiBUaGlzIEFPSSByZXByZXNlbnRzIHRoZSBzcGF0aWFsIGV4dGVudCBmcm9tIHdoaWNoIHRoZSBzYW1wbGVzIHdpbGwgYmUgZHJhd24uIEluIHRoaXMgc3BlY2lmaWMgY2FzZSwgdGhlIEFPSSBpcyBkZWZpbmVkIGFzIDMwLDAwMCBoZWN0YXJlcy4KCkNhbGN1bGF0ZSB0aGUgU2FtcGxlIFNpemU6IEJhc2VkIG9uIHRoZSByZXNvbHV0aW9uIG9mIHRoZSByYXN0ZXIgYW5kIHRoZSBkZXNpcmVkIEFPSSwgdGhlIHJlcXVpcmVkIG51bWJlciBvZiBwaXhlbHMgdG8gYmUgc2FtcGxlZCBpcyBjYWxjdWxhdGVkLiBUaGlzIGVuc3VyZXMgdGhhdCB0aGUgdG90YWwgYXJlYSBjb3ZlcmVkIGJ5IHRoZSBzYW1wbGVkIHBpeGVscyBjb3JyZXNwb25kcyB0byB0aGUgZGVmaW5lZCBBT0kuCgpQZXJmb3JtIFN0cmF0aWZpZWQgUmFuZG9tIFNhbXBsaW5nOiBUaGUgc3BhdFNhbXBsZSgpIGZ1bmN0aW9uIGZyb20gdGhlIHRlcnJhIHBhY2thZ2UgaW4gUiBpcyB1c2VkIHRvIHBlcmZvcm0gc3RyYXRpZmllZCByYW5kb20gc2FtcGxpbmcuIFRoaXMgZnVuY3Rpb24gYWxsb3dzIGZvciByYW5kb20gc2FtcGxpbmcgb2YgcGl4ZWxzIHdpdGhpbiB0aGUgZGVmaW5lZCBBT0ksIHdoaWxlIGFsc28gZXhjbHVkaW5nIHBpeGVscyB3aXRoICJOQSIgdmFsdWVzIGluIGFsbCBiYW5kcywgZW5zdXJpbmcgdGhhdCBvbmx5IHZhbGlkIGRhdGEgcG9pbnRzIGFyZSBpbmNsdWRlZCBpbiB0aGUgYW5hbHlzaXMuCgpSZXBlYXQgU2FtcGxpbmc6IFRvIHJlZHVjZSBwb3RlbnRpYWwgc2FtcGxpbmcgYmlhcyBhbmQgaW1wcm92ZSB0aGUgYWNjdXJhY3kgb2YgdGhlIGVzdGltYXRlcywgdGhlIHJhbmRvbSBzYW1wbGluZyBwcm9jZXNzIGlzIHJlcGVhdGVkIG11bHRpcGxlIHRpbWVzIChpbiB0aGlzIGNhc2UsIDMwIHRpbWVzKS4gVGhpcyBpcyBhbmFsb2dvdXMgdG8gdGhlIGNvbmNlcHQgb2YgYm9vdHN0cmFwcGluZywgd2hlcmUgcmVwZWF0ZWQgc2FtcGxpbmcgd2l0aCByZXBsYWNlbWVudCBpcyB1c2VkIHRvIGVzdGltYXRlIHRoZSBzYW1wbGluZyBkaXN0cmlidXRpb24gb2YgYSBzdGF0aXN0aWMuCgpDYWxjdWxhdGUgU3VtbWFyeSBTdGF0aXN0aWNzOiBGb3IgZWFjaCByZXBldGl0aW9uLCB0aGUgbWVhbiwgc3RhbmRhcmQgZGV2aWF0aW9uLCBhbmQgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIGFyZSBjYWxjdWxhdGVkIGZvciBlYWNoIGJhbmQgaW4gdGhlIHJhc3RlciBkYXRhc2V0LiBUaGlzIHByb3ZpZGVzIGEgbWVhc3VyZSBvZiB0aGUgY2VudHJhbCB0ZW5kZW5jeSBhbmQgdmFyaWFiaWxpdHkgb2YgdGhlIHNhbXBsZWQgZGF0YS4KClN5bnRoZXNpemUgUmVzdWx0czogVGhlIHJlc3VsdHMgZnJvbSBhbGwgcmVwZXRpdGlvbnMgYXJlIGNvbWJpbmVkIHRvIGNhbGN1bGF0ZSBhbiBvdmVyYWxsIG1lYW4gYW5kIGNvbmZpZGVuY2UgaW50ZXJ2YWwgZm9yIGVhY2ggYmFuZC4gVGhpcyBwcm92aWRlcyBhIG1vcmUgcm9idXN0IGVzdGltYXRlIG9mIHRoZSBleHBlY3RlZCB2YWx1ZXMsIGVmZmVjdGl2ZWx5IGNvcnJlY3RpbmcgZm9yIHBvdGVudGlhbCBvdXRsaWVycyBhbmQgcmVkdWNpbmcgdGhlIGluZmx1ZW5jZSBvZiBpbmRpdmlkdWFsIHNhbXBsZSB2YXJpYXRpb25zLgoKVGhlb3JldGljYWwgSnVzdGlmaWNhdGlvbgoKVGhlIHVzZSBvZiBzdHJhdGlmaWVkIHJhbmRvbSBzYW1wbGluZyBpcyBqdXN0aWZpZWQgYXMgaXQgZW5zdXJlcyB0aGF0IHRoZSBzYW1wbGUgaXMgcmVwcmVzZW50YXRpdmUgb2YgdGhlIGVudGlyZSBwb3B1bGF0aW9uIChpLmUuLCBhbGwgcGl4ZWxzIHdpdGhpbiB0aGUgQU9JKS4gQnkgZGl2aWRpbmcgdGhlIHBvcHVsYXRpb24gaW50byBzdHJhdGEgYW5kIHNhbXBsaW5nIGZyb20gZWFjaCBzdHJhdHVtLCB0aGlzIG1ldGhvZCByZWR1Y2VzIHRoZSB2YXJpYWJpbGl0eSBvZiB0aGUgZXN0aW1hdGVzIGNvbXBhcmVkIHRvIHNpbXBsZSByYW5kb20gc2FtcGxpbmcuIFRoaXMgaXMgcGFydGljdWxhcmx5IGltcG9ydGFudCB3aGVuIGRlYWxpbmcgd2l0aCBzcGF0aWFsIGRhdGEsIHdoZXJlIHRoZXJlIG1heSBiZSBpbmhlcmVudCBzcGF0aWFsIGF1dG9jb3JyZWxhdGlvbiBvciBoZXRlcm9nZW5laXR5LgoKVGhlIHJlcGVhdGVkIHNhbXBsaW5nIGFwcHJvYWNoIGZ1cnRoZXIgZW5oYW5jZXMgdGhlIHJvYnVzdG5lc3Mgb2YgdGhlIGVzdGltYXRlcyBieSBwcm92aWRpbmcgYSBkaXN0cmlidXRpb24gb2YgcG9zc2libGUgdmFsdWVzLiBUaGlzIGFsbG93cyBmb3IgdGhlIGNhbGN1bGF0aW9uIG9mIGNvbmZpZGVuY2UgaW50ZXJ2YWxzLCB3aGljaCBwcm92aWRlIGEgbWVhc3VyZSBvZiB0aGUgdW5jZXJ0YWludHkgYXNzb2NpYXRlZCB3aXRoIHRoZSBlc3RpbWF0ZXMuIEJ5IHN5bnRoZXNpemluZyB0aGUgcmVzdWx0cyBmcm9tIG11bHRpcGxlIHJlcGV0aXRpb25zLCB0aGUgb3ZlcmFsbCBlc3RpbWF0ZXMgYXJlIGxlc3Mgc3VzY2VwdGlibGUgdG8gdGhlIGluZmx1ZW5jZSBvZiBpbmRpdmlkdWFsIHNhbXBsZSB2YXJpYXRpb25zIGFuZCBwcm92aWRlIGEgbW9yZSBhY2N1cmF0ZSByZXByZXNlbnRhdGlvbiBvZiB0aGUgdHJ1ZSBwb3B1bGF0aW9uIHZhbHVlcy4KClJlZmVyZW5jZXMKCkNvY2hyYW4sIFcuIEcuICgxOTc3KS4gU2FtcGxpbmcgdGVjaG5pcXVlcyAoM3JkIGVkLikuIEpvaG4gV2lsZXkgJiBTb25zLgpMb2hyLCBTLiBMLiAoMjAxMCkuIFNhbXBsaW5nOiBEZXNpZ24gYW5kIGFuYWx5c2lzICgybmQgZWQuKS4gQnJvb2tzL0NvbGUuIDEgIAoxLgpCaXZhbmQsIFIuIFMuLCBQZWJlc21hLCBFLiBKLiwgJiBHw7NtZXotUnViaW8sIFYuICgyMDEzKS4gQXBwbGllZCBzcGF0aWFsIGRhdGEgYW5hbHlzaXMgd2l0aCBSICgybmQgZWQuKS4gU3ByaW5nZXIuCgoKIyMgNC4xIEVzcGlyaXRvIFNhbnRvCgojIyMgNC4xLjEgUHJlcGFyZSBEYXRhIEVzcCBTYW50by4KCkFsaWduIGFuZCByZXNhbXBlIGFsbCB0aGUgcmFzdGVyIGRhdGFzZXRzIHRvIHRoZSBzYW1lIGNycyBhbmQgb3JpZ2luLgoKYGBge3IgZmlsdGVyIGRhdGEgMSwgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0Kc2VydiA8LSByYXN0KGhlcmUoIkludGVydmVudGlvbnMiLCAiQnJhemlsX2ludGVydmVudGlvbiIsICJlc3Bfc2FudG9fYmtnLnRpZiIpKQphX2ZpbGVzIDwtIHRpZmZlc1tncmVwKCJCUkFaSUwiLCB0aWZmZXMpXQojYV9maWxlcyA8LSBhX2ZpbGVzWzJdCnNlcnZfMSA8LSBsYXBwbHkoYV9maWxlcywgcmFzdCkKdGYgPC0gYmFzZW5hbWUoYV9maWxlcykKdGVtcCA8LSB0cmltKHByb2plY3Qoc2Vydiwgc2Vydl8xW1sxXV0pKQpzZXJ2XzEgPC0gbGFwcGx5KHNlcnZfMSwgZnVuY3Rpb24ocil7CiAgciA8LSBjcm9wKHIsdGVtcCwgc25hcD0gImluIiwgZXh0ZW5kPVRSVUUpCiAgaWYgKCFjb21wYXJlR2VvbShyLCB0ZW1wLCBzdG9wT25FcnJvciA9IEZBTFNFKSkgewogICAgICBtZXNzYWdlKCJBbGlnbmluZyByYXN0ZXI6ICIsIG5hbWVzKHIpKQogICAgICAjIFJlc2FtcGxlIHRvIGFsaWduIHdpdGggdGhlIHRlbXBsYXRlCiAgICAgIHJlc2FtcGxlKHIsIHRlbXAsIG1ldGhvZCA9ICJiaWxpbmVhciIpCiAgICB9IGVsc2UgewogICAgICAjIFJldHVybiByYXN0ZXIgYXMgaXMgaWYgYWxyZWFkeSBhbGlnbmVkCiAgICAgIG1lc3NhZ2UoIlJhc3RlciBhbHJlYWR5IGFsaWduZWQ6ICIsIG5hbWVzKHIpKQogICAgICByCiAgICB9CiAgciA8LSB0cmltKHIpCiAgI3IgPC0gbWFzayhyLHRlbXApCnIgPC0gcHJvamVjdChyLCBzZXJ2LCBtZXRob2QgPSAnYmlsaW5lYXInKQp9KQoKc2Vydl8xIDwtIGxhcHBseShzZXJ2XzEsIGZ1bmN0aW9uKHIpewogIHIgPC0gbWFzayhyLHNlcnYpCn0pCgptYXAoMTpsZW5ndGgoc2Vydl8xKSwgZnVuY3Rpb24oeCkgd3JpdGVSYXN0ZXIoc2Vydl8xW1t4XV0sIHBhc3RlMChoZXJlKCJJbnRlcnZlbnRpb25zIiwgIkJyYXppbF9pbnRlcnZlbnRpb24iKSwgJy8nLCB0Zlt4XSksIG92ZXJ3cml0ZT1UUlVFKSkKc2Vydl8xIDwtIGxhcHBseSh0aWZmZXMsIHJhc3QpCnNlcnZfMSA8LSAoZG8uY2FsbChjLHNlcnZfMSkpCnNlcnZfMSA8LSB0cmltKG1lcmdlKHNlcnZfMSxzZXJ2KSkgI2FkZCBiYWNrZ3JvdW5kIG9mIFplcm9zCndyaXRlUmFzdGVyKHNlcnZfMSwgcGFzdGUwKGhlcmUoIkludGVydmVudGlvbnMiLCAiQnJhemlsX2ludGVydmVudGlvbiIpLCcvJywgJ3NlcnZfQlJBWklMLnRpZicpLCBvdmVyd3JpdGU9VFJVRSkKYGBgCgoKIyMjIDQuMS4yIFJ1biBTYW1wbGluZyBhbmQgU3ludGV0aXplIHJlc3VsdHMgLSBFc3Bpcml0byBTYW50bwoKSGVyZSwgd2UgYXJlIHNhbXBsaW5nIHRoZSBkYXRhIGZvciBvYnRhaW4gZXN0aW1hdGUgb2YgdGhlIGV4cGVjdGVkIHJlc3RvcmF0aW9uIGdhaW5zIGFzc3VtaW5nIHJhbmRvbWx5IHNlbGVjdGVkIHBpeGVscyBleHRyYWN0ZWQgZm9ybSB0aGUgcG90ZW50aWFsIHJlc3RvcmF0aW9uIGFyZWFzLiBBZ2Fpbiwgc29tZSBhc3N1bXB0aW9ucyB3aWxsIGhhdmUgdG8gYmUgcmV2aWV3ZWQsIGJ1dCB0aGlzIGlzIGFuIGluaXRpYWwgYXNzZXNzbWVudC4KVGhlIHRhcmdldGVkIGludGVydmVudGlvbiBhcmVhIGlzIDMwLjIwMCBoYS4KCmBgYHtyIHNhbXBsaW5nIHRhcmdldCBhcmVhcyBicmF6aWwsIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CnNlcnZfMSA8LSByYXN0KGhlcmUoIkludGVydmVudGlvbnMiLCAiQnJhemlsX2ludGVydmVudGlvbiIsJy8nLCAnc2Vydl9CUkFaSUwudGlmJykpCnJlc3RfbSA8LSByYXN0KGhlcmUoJ0ludGVydmVudGlvbnMnLCAnQnJhemlsX2ludGVydmVudGlvbicsICdTU19ncmlzY29tLnRpZicpKQpyY2wgPC0gbWF0cml4KGMoCiAgLUluZiwgMCwgMCwgICMgQW55IHZhbHVlIGZyb20gLUluZmluaXR5IHRvIDAgcmVtYWlucyAwCiAgMCwgSW5mLCAxICAgIyBBbnkgdmFsdWUgZnJvbSAwIHRvIEluZmluaXR5IGJlY29tZXMgMQopLCBuY29sID0gMywgYnlyb3cgPSBUUlVFKQpyZXN0X20gPC0gY2xhc3NpZnkocmVzdF9tLCByY2wpCgpyZXN0X20gPC1wcm9qZWN0KHJlc3RfbSwgc2Vydl8xKQpyZXN0X20gPC0gdGVycmE6OnJlc2FtcGxlKHJlc3RfbSwgc2Vydl8xKQpzZXJ2XzEgPC0gbWFzayhzZXJ2XzEscmVzdF9tLCBtYXNrdmFsdWVzPTApCiNDYWxjdWxhdGUgdGhlIG51bWJlciBvZiBwaXhlbHMgbmVlZGVkIGZvciAzMCwwMDAgaGVjdGFyZXMKcGl4ZWxfYXJlYSA8LSAzMCAqIDMwICAjIEFyZWEgb2YgYSBzaW5nbGUgcGl4ZWwgaW4gc3F1YXJlIG1ldGVycyAoMzBtIHJlc29sdXRpb24pCmhlY3RhcmVfYXJlYSA8LSAxMDAwMCAgIyBBcmVhIG9mIG9uZSBoZWN0YXJlIGluIHNxdWFyZSBtZXRlcnMKcGl4ZWxzX25lZWRlZCA8LSByb3VuZCgoMzAyMDAgKiBoZWN0YXJlX2FyZWEpIC8gcGl4ZWxfYXJlYSkKCiMgTnVtYmVyIG9mIHJlcGV0aXRpb25zCm5fcmVwZXRpdGlvbnMgPC0gMzAKIyBGdW5jdGlvbiB0byBwZXJmb3JtIHRoZSBzYW1wbGluZyBhbmQgY2FsY3VsYXRpb25zCnNhbXBsZV9hbmRfY2FsY3VsYXRlIDwtIGZ1bmN0aW9uKGksIHJhc3RlciwgcGl4ZWxzX25lZWRlZCkgewogICMgU2FtcGxlIHBpeGVscyBhbmQgZGlyZWN0bHkgZXh0cmFjdCB2YWx1ZXMgKHdpdGhvdXQgbmEucm0pCiAgc2FtcGxlX3ZhbHVlcyA8LSBzcGF0U2FtcGxlKHJhc3Rlciwgc2l6ZSA9IHBpeGVsc19uZWVkZWQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRob2QgPSAicmFuZG9tIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hLnJtID0gRkFMU0UsICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXMucG9pbnRzID0gRkFMU0UsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4eSA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZXMgPSBUUlVFKSAKCiAgIyBSZW1vdmUgcm93cyB3aGVyZSBBTEwgdmFsdWVzIGFyZSBOQQogIHNhbXBsZV92YWx1ZXMgPC0gc2FtcGxlX3ZhbHVlc1tyb3dTdW1zKGlzLm5hKHNhbXBsZV92YWx1ZXMpKSAhPSBuY29sKHNhbXBsZV92YWx1ZXMpLCBdCgogICMgSWYgbm90IGVub3VnaCBzYW1wbGVzIGFmdGVyIHJlbW92aW5nIE5BcywgcmVzYW1wbGUKICBpZiAobnJvdyhzYW1wbGVfdmFsdWVzKSA8IHBpeGVsc19uZWVkZWQpIHsKICAgIHNhbXBsZV92YWx1ZXMgPC0gcmJpbmQoCiAgICAgIHNhbXBsZV92YWx1ZXMsCiAgICAgIHNwYXRTYW1wbGUocmFzdGVyLCBzaXplID0gcGl4ZWxzX25lZWRlZCAtIG5yb3coc2FtcGxlX3ZhbHVlcyksCiAgICAgICAgICAgICAgICAgbWV0aG9kID0gInJhbmRvbSIsIG5hLnJtID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgYXMucG9pbnRzID0gRkFMU0UsIHh5ID0gRkFMU0UsIHZhbHVlcyA9IFRSVUUpCiAgICApCiAgfQoKICAjIENhbGN1bGF0ZSBzdW1tYXJ5IHN0YXRpc3RpY3MKICBiYW5kX3N0YXRzIDwtIGFwcGx5KHNhbXBsZV92YWx1ZXMsIDIsIGZ1bmN0aW9uKHgpIHsgCiAgICBtZWFuX3ZhbCA8LSBtZWFuKHgpCiAgICBzZF92YWwgPC0gc2QoeCkKICAgIG5fdmFsIDwtIGxlbmd0aCh4KQogICAgc2VfdmFsIDwtIHNkX3ZhbCAvIHNxcnQobl92YWwpCiAgICBtYXJnaW5fZXJyb3IgPC0gcXQoMC45NzUsIGRmID0gbl92YWwgLSAxKSAqIHNlX3ZhbAogICAgbG93ZXJfY2kgPC0gbWVhbl92YWwgLSBtYXJnaW5fZXJyb3IKICAgIHVwcGVyX2NpIDwtIG1lYW5fdmFsICsgbWFyZ2luX2Vycm9yCiAgICByZXR1cm4oYyhtZWFuID0gbWVhbl92YWwsIGxvd2VyX2NpID0gbG93ZXJfY2ksIHVwcGVyX2NpID0gdXBwZXJfY2kpKQogIH0pCgogIGJhbmRfc3RhdHNfZGYgPC0gYXMuZGF0YS5mcmFtZSh0KGJhbmRfc3RhdHMpKQogIGJhbmRfc3RhdHNfZGYkcmVwZXRpdGlvbiA8LSBpCgogICMgQ2FsY3VsYXRlIHN1bSBvZiBwaXhlbCB2YWx1ZXMgZm9yIGVhY2ggYmFuZAogIGJhbmRfc3VtcyA8LSBjb2xTdW1zKHNhbXBsZV92YWx1ZXMpIAogIGJhbmRfc3RhdHNfZGYkc3VtIDwtIGJhbmRfc3VtcwoKICByZXR1cm4oYmFuZF9zdGF0c19kZikKfQoKIyBVc2luZyBtY2xhcHBseSAocGFyYWxsZWwgcHJvY2Vzc2luZykKbnVtX2NvcmVzIDwtIDE1IApyZXN1bHRzX2xpc3QgPC0gbWNsYXBwbHkoMTpuX3JlcGV0aXRpb25zLCBzYW1wbGVfYW5kX2NhbGN1bGF0ZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICByYXN0ZXIgPSBzZXJ2XzEsIAogICAgICAgICAgICAgICAgICAgICAgICAgcGl4ZWxzX25lZWRlZCA9IHBpeGVsc19uZWVkZWQsCiAgICAgICAgICAgICAgICAgICAgICAgICBtYy5jb3JlcyA9IG51bV9jb3JlcykgCgpyZXN1bHRzX2xpc3QgPC0gbGFwcGx5KHJlc3VsdHNfbGlzdCwgZnVuY3Rpb24oZGYpewogIGRmIDwtIGRmICU+JSBtdXRhdGUoYmFuZD1yb3duYW1lcyhkZikpCn0pCiMgQ29tYmluZSBhbGwgcmVzdWx0cyBpbnRvIGEgc2luZ2xlIGRhdGEgZnJhbWUKYWxsX3Jlc3VsdHMgPC0gYXNfdGliYmxlKGRvLmNhbGwocmJpbmQsIHJlc3VsdHNfbGlzdCkpCgoKIyBBZGQgbmV3IGNvbHVtbnMgd2l0aCB0aGUgc2VydmljZSBuYW1lcyBhbmQgdW5pdHMuCmFsbF9yZXN1bHRzIDwtIGFsbF9yZXN1bHRzICU+JQogIG11dGF0ZShTZXJ2aWNlID0gY2FzZV93aGVuKAogICAgYmFuZCA9PSAiY3ZfaGFiaXRhdF92YWx1ZV9TYzN2MS1FU0Ftb2QyX3YyX21kNV82NDA4MmIiIH4gIkNvYXN0YWwgUHJvdGVjdGlvbiIsCiAgICBiYW5kID09ICJuYXR1cmVfYWNjZXNzX2RpZmZfU2MzdjFfUE5Wbm9hZy1lc2EyMDIwIiB+ICJOYXR1cmUgQWNjZXNzIiwKICAgIGJhbmQgPT0gIm5pdHJvZ2VuX0VTQW1vZDItU2MzdjFfbWQ1XzAyNGEzNiIgfiAiTml0cm9nZW4gRXhwb3J0IiwKICAgIGJhbmQgPT0gInBvbGxpbmF0aW9uX3BwbF9mZWRfb25fYWdfMTBzX1NjM3YxX1BOVm5vYWctZXNhMjAyMF9tZDVfNDA1Yzg4IiB+ICJQb2xsaW5hdGlvbiIsCiAgICBiYW5kID09ICJwb2xsaW5hdGlvbl9wcGxfZmVkX29uX2hhYl9TYzN2MV9QTlZfbm9fYWctRVNBX21kNV81NzY3OTAiIH4gIlBvbGxpbmF0aW9uIChwZW9wbGUgZmVkIG9uIEhhYikiLAogICAgYmFuZCA9PSAic2VkaW1lbnRfRVNBbW9kMi1TYzN2MV9tZDVfMTQ5MDc4IiB+ICJTZWRpbWVudCBFeHBvcnQiLAogICAgIyAuLi4gYWRkIG1vcmUgY2FzZXMgZm9yIG90aGVyIGJhbmRzIC4uLgogICAgVFJVRSB+IGJhbmQgICMgS2VlcCB0aGUgb3JpZ2luYWwgYmFuZCBuYW1lIGlmIG5vIG1hdGNoCiAgKSkKCmFsbF9yZXN1bHRzIDwtIGFsbF9yZXN1bHRzICU+JQogIG11dGF0ZSh1bml0cyA9IGNhc2Vfd2hlbigKICAgIGJhbmQgPT0gImN2X2hhYml0YXRfdmFsdWVfU2MzdjEtRVNBbW9kMl92Ml9tZDVfNjQwODJiIiB+ICJSaXNrIFJlZHVjdGlvbiBJbmRleCIsCiAgICBiYW5kID09ICJuYXR1cmVfYWNjZXNzX2RpZmZfU2MzdjFfUE5Wbm9hZy1lc2EyMDIwIiB+ICJQZW9wbGUgd2l0aGluIDEgaG91ciIsCiAgICBiYW5kID09ICJuaXRyb2dlbl9FU0Ftb2QyLVNjM3YxX21kNV8wMjRhMzYiIH4gIk5pdHJvZ2VuIEV4cG9ydCAoa2cvaGEveWVhcikiLAogICAgYmFuZCA9PSAicG9sbGluYXRpb25fcHBsX2ZlZF9vbl9hZ18xMHNfU2MzdjFfUE5Wbm9hZy1lc2EyMDIwX21kNV80MDVjODgiIH4gIlBvbGxpbmF0aW9uIChlcXVpdmFsZW50IHBlb3BsZSBmZWQpIiwKICAgIGJhbmQgPT0gInBvbGxpbmF0aW9uX3BwbF9mZWRfb25faGFiX1NjM3YxX1BOVl9ub19hZy1FU0FfbWQ1XzU3Njc5MCIgfiAiUG9sbGluYXRpb24gKHBlb3BsZSBmZWQgb24gaGFiKSIsCiAgICBiYW5kID09ICJzZWRpbWVudF9FU0Ftb2QyLVNjM3YxX21kNV8xNDkwNzgiIH4gIlNlZGltZW50IEV4cG9ydCAodG9uL2tnL3llYXIpIiwKICAgICMgLi4uIGFkZCBtb3JlIGNhc2VzIGZvciBvdGhlciBiYW5kcyAuLi4KICAgIFRSVUUgfiBiYW5kICAjIEtlZXAgdGhlIG9yaWdpbmFsIGJhbmQgbmFtZSBpZiBubyBtYXRjaAogICkpCgphbGxfcmVzdWx0cyA8LSBhbGxfcmVzdWx0cyAlPiUKICBtdXRhdGUoY29sb3IgPSBjYXNlX3doZW4oCiAgICBiYW5kID09ICJjdl9oYWJpdGF0X3ZhbHVlX1NjM3YxLUVTQW1vZDJfdjJfbWQ1XzY0MDgyYiIgfiAiIzdhMDE3NyIsCiAgICBiYW5kID09ICJuYXR1cmVfYWNjZXNzX2RpZmZfU2MzdjFfUE5Wbm9hZy1lc2EyMDIwIiB+ICIjQTU3QzAwIiwKICAgIGJhbmQgPT0gIm5pdHJvZ2VuX0VTQW1vZDItU2MzdjFfbWQ1XzAyNGEzNiIgfiAiIzJjOTQ0YyIsCiAgICBiYW5kID09ICJwb2xsaW5hdGlvbl9wcGxfZmVkX29uX2FnXzEwc19TYzN2MV9QTlZub2FnLWVzYTIwMjBfbWQ1XzQwNWM4OCIgfiAiI2RkMWM3NyIsCiAgICBiYW5kID09ICJwb2xsaW5hdGlvbl9wcGxfZmVkX29uX2hhYl9TYzN2MV9QTlZfbm9fYWctRVNBX21kNV81NzY3OTAiIH4gIiNkZDFiNTYiLAogICAgYmFuZCA9PSAic2VkaW1lbnRfRVNBbW9kMi1TYzN2MV9tZDVfMTQ5MDc4IiB+ICIjMDgzMDZiIiwKICAgICMgLi4uIGFkZCBtb3JlIGNhc2VzIGZvciBvdGhlciBiYW5kcyAuLi4KICAgIFRSVUUgfiBiYW5kICAjIEtlZXAgdGhlIG9yaWdpbmFsIGJhbmQgbmFtZSBpZiBubyBtYXRjaAogICkpCnNhdmUoYWxsX3Jlc3VsdHMsIGZpbGU9IGhlcmUoIkludGVydmVudGlvbnMiLCAiQnJhemlsX2ludGVydmVudGlvbiIsICJhbGxfcmVzX2JyYS5SRGF0YSIpKQpgYGAKIAogCiMjIyA0LjEuMyBQbG90IFJlc3VsdHMgRXNwaXJpdG8gU2FudG8KCmBgYHtyIHBsb3QgYnJhemlsIG91dHB1cywgZWNobz1GQUxTRX0KbG9hZChoZXJlKCJJbnRlcnZlbnRpb25zIiwgIkJyYXppbF9pbnRlcnZlbnRpb24iLCAiYWxsX3Jlc19icmEuUkRhdGEiKSkKZGYgPC1hbGxfcmVzdWx0cyAlPiUgIGZpbHRlcihiYW5kIT0ibmF0dXJlX2FjY2Vzc19kaWZmX1NjM3YxX1BOVm5vYWctZXNhMjAyMCIpICU+JSBmaWx0ZXIoYmFuZCE9ICJwb2xsaW5hdGlvbl9wcGxfZmVkX29uX2hhYl9TYzN2MV9QTlZfbm9fYWctRVNBX21kNV81NzY3OTAiKQojIEFzc3VtaW5nIHlvdXIgJ2FsbF9yZXN1bHRzJyBkYXRhIGZyYW1lIGhhcyB0aGUgY29sdW1ucyAnU2VydmljZScsICd1bml0cycsIGFuZCAnY29sb3InCiMgQXNzdW1pbmcgeW91ciAnYWxsX3Jlc3VsdHMnIGRhdGEgZnJhbWUgaGFzIHRoZSBjb2x1bW5zICdTZXJ2aWNlJywgJ3VuaXRzJywgYW5kICdjb2xvcicKCiMgR2VuZXJhdGUgdGhlIGdncGxvdCBvYmplY3QKcGxvdCA8LSBnZ3Bsb3QoZGYsIGFlcyh5ID0gc3VtLCBmaWxsID0gY29sb3IpKSArCiAgZ2VvbV9ib3hwbG90KCkgKwogIGxhYnModGl0bGUgPSBzdHJfd3JhcCgiVG90YWwgZXN0aW1hdGVkIHNlcnZpY2UgY2hhbmdlIGluIHVuaXRzIGZvciB0aGUgdGFyZ2V0IGludGVydmVudGlvbiBhcmVhIC0gRXNwaXJpdG8gU2FudG8iLCB3aWR0aCA9IDUwKSwgCiAgICAgICB5ID0gIlRvdGFsIFN1bSBWYWx1ZSIpICsKICB0aGVtZV9idygpICsKICB0aGVtZSgKICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50aWNrcy54ID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLAogICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiksCiAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIgICMgUmVtb3ZlIGxlZ2VuZCBzaW5jZSBjb2xvciBpcyBhbHJlYWR5IG1hcHBlZAogICkgKwogIHNjYWxlX2ZpbGxfaWRlbnRpdHkoKSArIAogIGZhY2V0X3dyYXAofiBTZXJ2aWNlLCBzY2FsZXMgPSAiZnJlZV95IiwgbGFiZWxsZXIgPSBsYWJlbGxlcihTZXJ2aWNlID0gbGFiZWxfd3JhcF9nZW4od2lkdGggPSAxMCkpKSArICAKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gZnVuY3Rpb24oeCkgewogICAgaWYgKG1heCh4LCBuYS5ybSA9IFRSVUUpID4gMTAwMDAwKSB7CiAgICAgIHBhc3RlMChmb3JtYXQoeCAvIDEwMDAsIGJpZy5tYXJrID0gIi4iLCBkZWNpbWFsLm1hcmsgPSAiLCIpLCAiayIpCiAgICB9IGVsc2UgewogICAgICBmb3JtYXQoeCwgYmlnLm1hcmsgPSAiLiIsIGRlY2ltYWwubWFyayA9ICIsIikKICAgIH0KICB9KSAKcGxvdApgYGAKCiMjIDQuMiBZdWNhdGFuCgpUaGUgYXBwcm9hY2ggaXMgdGhlIHNhbWUgYXMgaW4gQnJhemlsLgpUd28gbWFpbiBpbnRlcnZlbnRpb24gYXJlYXMgd2VyZSB1c2VkIHRybyBidWlsZCB0aGUgZmluYWwgcG9seWdvbjogdGhlIGphZ3VhciBjb3JyaWRvciBhbmQgCiMjIyA0LjIuMSBQcmVwYXJlIERhdGEgWXVjYXRhbi4KQWxpZ24gYW5kIHJlc2FtcGxlIGFsbCB0aGUgcmFzdGVyIGJhbmRzIHRvIHRoZSBhbWUgY3JzIGFuZCBvcmlnaW4uCgpgYGB7ciBmaWx0ZXIgZGF0YSAyLCBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQpzZXJ2IDwtIHJhc3QoaGVyZSgiSW50ZXJ2ZW50aW9ucyIsICJNZXhfaW50ZXJ2ZW50aW9uIiwgInl1Y2F0YW5fYmtnLnRpZiIpKQphX2ZpbGVzIDwtIHRpZmZlc1tncmVwKCJNRVhJQ08iLCB0aWZmZXMpXQojYV9maWxlcyA8LSBhX2ZpbGVzWzJdCnNlcnZfMSA8LSBsYXBwbHkoYV9maWxlcywgcmFzdCkKdGYgPC0gYmFzZW5hbWUoYV9maWxlcykKdGVtcCA8LSB0cmltKHByb2plY3Qoc2Vydiwgc2Vydl8xW1sxXV0pKQpzZXJ2XzEgPC0gbGFwcGx5KHNlcnZfMSwgZnVuY3Rpb24ocil7CiAgciA8LSBjcm9wKHIsdGVtcCwgc25hcD0gImluIiwgZXh0ZW5kPVRSVUUpCiAgaWYgKCFjb21wYXJlR2VvbShyLCB0ZW1wLCBzdG9wT25FcnJvciA9IEZBTFNFKSkgewogICAgICBtZXNzYWdlKCJBbGlnbmluZyByYXN0ZXI6ICIsIG5hbWVzKHIpKQogICAgICAjIFJlc2FtcGxlIHRvIGFsaWduIHdpdGggdGhlIHRlbXBsYXRlCiAgICAgIHJlc2FtcGxlKHIsIHRlbXAsIG1ldGhvZCA9ICJiaWxpbmVhciIpCiAgICB9IGVsc2UgewogICAgICAjIFJldHVybiByYXN0ZXIgYXMgaXMgaWYgYWxyZWFkeSBhbGlnbmVkCiAgICAgIG1lc3NhZ2UoIlJhc3RlciBhbHJlYWR5IGFsaWduZWQ6ICIsIG5hbWVzKHIpKQogICAgICByCiAgICB9CiAgciA8LSB0cmltKHIpCiAgI3IgPC0gbWFzayhyLHRlbXApCnIgPC0gcHJvamVjdChyLCBzZXJ2LCBtZXRob2QgPSAnYmlsaW5lYXInKQp9KQoKc2Vydl8xIDwtIGxhcHBseShzZXJ2XzEsIGZ1bmN0aW9uKHIpewogIHIgPC0gbWFzayhyLHNlcnYpCn0pCgptYXAoMTpsZW5ndGgoc2Vydl8xKSwgZnVuY3Rpb24oeCkgd3JpdGVSYXN0ZXIoc2Vydl8xW1t4XV0sIHBhc3RlMChoZXJlKCJJbnRlcnZlbnRpb25zIiwgIk1leF9pbnRlcnZlbnRpb24iKSwgJy8nLCB0Zlt4XSksIG92ZXJ3cml0ZT1UUlVFKSkKc2Vydl8xIDwtIGxhcHBseSh0aWZmZXMsIHJhc3QpCnNlcnZfMSA8LSAoZG8uY2FsbChjLHNlcnZfMSkpCnNlcnZfMSA8LSB0cmltKG1lcmdlKHNlcnZfMSxzZXJ2KSkgI2FkZCBiYWNrZ3JvdW5kIG9mIFplcm9zCndyaXRlUmFzdGVyKHNlcnZfMSwgcGFzdGUwKGhlcmUoIkludGVydmVudGlvbnMiLCAiTWV4X2ludGVydmVudGlvbiIpLCcvJywgJ3NlcnZfTUVYSUNPLnRpZicpLCBvdmVyd3JpdGU9VFJVRSkKYGBgCgojIyMgNC4xLjIgUnVuIFNhbXBsaW5nIGFuZCBTeW50aGV0aXplIHJlc3VsdHMgLSBZdWNhdGFuCgpgYGB7ciBzYW1wbGluZyB0YXJnZSBhcmVhIE1YLCBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQojc2Vydl8xIDwtIHJhc3QoaGVyZSgiSW50ZXJ2ZW50aW9ucyIsICJNZXhfaW50ZXJ2ZW50aW9uIiwnLycsICdzZXJ2X01FWElDTy50aWYnKSkKcmVzdF9tIDwtIHJhc3QoaGVyZSgnSW50ZXJ2ZW50aW9ucycsICdNZXhfaW50ZXJ2ZW50aW9uJywgJ01leF9ncmlzY29tLnRpZicpKQpyY2wgPC0gbWF0cml4KGMoCiAgLUluZiwgMCwgMCwgICMgQW55IHZhbHVlIGZyb20gLUluZmluaXR5IHRvIDAgcmVtYWlucyAwCiAgMCwgSW5mLCAxICAgIyBBbnkgdmFsdWUgZnJvbSAwIHRvIEluZmluaXR5IGJlY29tZXMgMQopLCBuY29sID0gMywgYnlyb3cgPSBUUlVFKQpyZXN0X20gPC0gY2xhc3NpZnkocmVzdF9tLCByY2wpCgpyZXN0X20gPC1wcm9qZWN0KHJlc3RfbSwgc2Vydl8xKQpyZXN0X20gPC0gdGVycmE6OnJlc2FtcGxlKHJlc3RfbSwgc2Vydl8xKQpzZXJ2XzEgPC0gbWFzayhzZXJ2XzEscmVzdF9tLCBtYXNrdmFsdWVzPTApCiMgQ2FsY3VsYXRlIHRoZSBudW1iZXIgb2YgcGl4ZWxzIG5lZWRlZCBmb3IgMTUsMDAwIGhlY3RhcmVzCnBpeGVsX2FyZWEgPC0gMzAgKiAzMCAgIyBBcmVhIG9mIGEgc2luZ2xlIHBpeGVsIGluIHNxdWFyZSBtZXRlcnMgKDMwbSByZXNvbHV0aW9uKQpoZWN0YXJlX2FyZWEgPC0gMTAwMDAgICMgQXJlYSBvZiBvbmUgaGVjdGFyZSBpbiBzcXVhcmUgbWV0ZXJzCnBpeGVsc19uZWVkZWQgPC0gcm91bmQoKDE1MDAwICogaGVjdGFyZV9hcmVhKSAvIHBpeGVsX2FyZWEpCgojIE51bWJlciBvZiByZXBldGl0aW9ucwpuX3JlcGV0aXRpb25zIDwtIDMwCiMgRnVuY3Rpb24gdG8gcGVyZm9ybSB0aGUgc2FtcGxpbmcgYW5kIGNhbGN1bGF0aW9ucwpzYW1wbGVfYW5kX2NhbGN1bGF0ZSA8LSBmdW5jdGlvbihpLCByYXN0ZXIsIHBpeGVsc19uZWVkZWQpIHsKICAjIFNhbXBsZSBwaXhlbHMgYW5kIGRpcmVjdGx5IGV4dHJhY3QgdmFsdWVzICh3aXRob3V0IG5hLnJtKQogIHNhbXBsZV92YWx1ZXMgPC0gc3BhdFNhbXBsZShyYXN0ZXIsIHNpemUgPSBwaXhlbHNfbmVlZGVkLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kID0gInJhbmRvbSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYS5ybSA9IEZBTFNFLCAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzLnBvaW50cyA9IEZBTFNFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeHkgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVzID0gVFJVRSkgCgogICMgUmVtb3ZlIHJvd3Mgd2hlcmUgQUxMIHZhbHVlcyBhcmUgTkEKICBzYW1wbGVfdmFsdWVzIDwtIHNhbXBsZV92YWx1ZXNbcm93U3Vtcyhpcy5uYShzYW1wbGVfdmFsdWVzKSkgIT0gbmNvbChzYW1wbGVfdmFsdWVzKSwgXQoKICAjIElmIG5vdCBlbm91Z2ggc2FtcGxlcyBhZnRlciByZW1vdmluZyBOQXMsIHJlc2FtcGxlCiAgaWYgKG5yb3coc2FtcGxlX3ZhbHVlcykgPCBwaXhlbHNfbmVlZGVkKSB7CiAgICBzYW1wbGVfdmFsdWVzIDwtIHJiaW5kKAogICAgICBzYW1wbGVfdmFsdWVzLAogICAgICBzcGF0U2FtcGxlKHJhc3Rlciwgc2l6ZSA9IHBpeGVsc19uZWVkZWQgLSBucm93KHNhbXBsZV92YWx1ZXMpLAogICAgICAgICAgICAgICAgIG1ldGhvZCA9ICJyYW5kb20iLCBuYS5ybSA9IFRSVUUsIAogICAgICAgICAgICAgICAgIGFzLnBvaW50cyA9IEZBTFNFLCB4eSA9IEZBTFNFLCB2YWx1ZXMgPSBUUlVFKQogICAgKQogIH0KCiAgIyBDYWxjdWxhdGUgc3VtbWFyeSBzdGF0aXN0aWNzCiAgYmFuZF9zdGF0cyA8LSBhcHBseShzYW1wbGVfdmFsdWVzLCAyLCBmdW5jdGlvbih4KSB7IAogICAgbWVhbl92YWwgPC0gbWVhbih4KQogICAgc2RfdmFsIDwtIHNkKHgpCiAgICBuX3ZhbCA8LSBsZW5ndGgoeCkKICAgIHNlX3ZhbCA8LSBzZF92YWwgLyBzcXJ0KG5fdmFsKQogICAgbWFyZ2luX2Vycm9yIDwtIHF0KDAuOTc1LCBkZiA9IG5fdmFsIC0gMSkgKiBzZV92YWwKICAgIGxvd2VyX2NpIDwtIG1lYW5fdmFsIC0gbWFyZ2luX2Vycm9yCiAgICB1cHBlcl9jaSA8LSBtZWFuX3ZhbCArIG1hcmdpbl9lcnJvcgogICAgcmV0dXJuKGMobWVhbiA9IG1lYW5fdmFsLCBsb3dlcl9jaSA9IGxvd2VyX2NpLCB1cHBlcl9jaSA9IHVwcGVyX2NpKSkKICB9KQoKICBiYW5kX3N0YXRzX2RmIDwtIGFzLmRhdGEuZnJhbWUodChiYW5kX3N0YXRzKSkKICBiYW5kX3N0YXRzX2RmJHJlcGV0aXRpb24gPC0gaQoKICAjIENhbGN1bGF0ZSBzdW0gb2YgcGl4ZWwgdmFsdWVzIGZvciBlYWNoIGJhbmQKICBiYW5kX3N1bXMgPC0gY29sU3VtcyhzYW1wbGVfdmFsdWVzKSAKICBiYW5kX3N0YXRzX2RmJHN1bSA8LSBiYW5kX3N1bXMKCiAgcmV0dXJuKGJhbmRfc3RhdHNfZGYpCn0KCiMgVXNpbmcgbWNsYXBwbHkgKHBhcmFsbGVsIHByb2Nlc3NpbmcpCm51bV9jb3JlcyA8LSAxNSAKcmVzdWx0c19saXN0IDwtIG1jbGFwcGx5KDE6bl9yZXBldGl0aW9ucywgc2FtcGxlX2FuZF9jYWxjdWxhdGUsIAogICAgICAgICAgICAgICAgICAgICAgICAgcmFzdGVyID0gc2Vydl8xLCAKICAgICAgICAgICAgICAgICAgICAgICAgIHBpeGVsc19uZWVkZWQgPSBwaXhlbHNfbmVlZGVkLAogICAgICAgICAgICAgICAgICAgICAgICAgbWMuY29yZXMgPSBudW1fY29yZXMpIAoKcmVzdWx0c19saXN0IDwtIGxhcHBseShyZXN1bHRzX2xpc3QsIGZ1bmN0aW9uKGRmKXsKICBkZiA8LSBkZiAlPiUgbXV0YXRlKGJhbmQ9cm93bmFtZXMoZGYpKQp9KQojIENvbWJpbmUgYWxsIHJlc3VsdHMgaW50byBhIHNpbmdsZSBkYXRhIGZyYW1lCmFsbF9yZXN1bHRzIDwtIGFzX3RpYmJsZShkby5jYWxsKHJiaW5kLCByZXN1bHRzX2xpc3QpKQoKCiMgQWRkIG5ldyBjb2x1bW5zIHdpdGggdGhlIHNlcnZpY2UgbmFtZXMgYW5kIHVuaXRzLgphbGxfcmVzdWx0cyA8LSBhbGxfcmVzdWx0cyAlPiUKICBtdXRhdGUoU2VydmljZSA9IGNhc2Vfd2hlbigKICAgIGJhbmQgPT0gImN2X2hhYml0YXRfdmFsdWVfU2MzdjEtRVNBbW9kMl92Ml9tZDVfNjQwODJiIiB+ICJDb2FzdGFsIFByb3RlY3Rpb24iLAogICAgYmFuZCA9PSAibmF0dXJlX2FjY2Vzc19kaWZmX1NjM3YxX1BOVm5vYWctZXNhMjAyMCIgfiAiTmF0dXJlIEFjY2VzcyIsCiAgICBiYW5kID09ICJuaXRyb2dlbl9FU0Ftb2QyLVNjM3YxX21kNV8wMjRhMzYiIH4gIk5pdHJvZ2VuIEV4cG9ydCIsCiAgICBiYW5kID09ICJwb2xsaW5hdGlvbl9wcGxfZmVkX29uX2FnXzEwc19TYzN2MV9QTlZub2FnLWVzYTIwMjBfbWQ1XzQwNWM4OCIgfiAiUG9sbGluYXRpb24iLAogICAgYmFuZCA9PSAicG9sbGluYXRpb25fcHBsX2ZlZF9vbl9oYWJfU2MzdjFfUE5WX25vX2FnLUVTQV9tZDVfNTc2NzkwIiB+ICJQb2xsaW5hdGlvbiAocGVvcGxlIGZlZCBvbiBIYWIpIiwKICAgIGJhbmQgPT0gInNlZGltZW50X0VTQW1vZDItU2MzdjFfbWQ1XzE0OTA3OCIgfiAiU2VkaW1lbnQgRXhwb3J0IiwKICAgICMgLi4uIGFkZCBtb3JlIGNhc2VzIGZvciBvdGhlciBiYW5kcyAuLi4KICAgIFRSVUUgfiBiYW5kICAjIEtlZXAgdGhlIG9yaWdpbmFsIGJhbmQgbmFtZSBpZiBubyBtYXRjaAogICkpCgphbGxfcmVzdWx0cyA8LSBhbGxfcmVzdWx0cyAlPiUKICBtdXRhdGUodW5pdHMgPSBjYXNlX3doZW4oCiAgICBiYW5kID09ICJjdl9oYWJpdGF0X3ZhbHVlX1NjM3YxLUVTQW1vZDJfdjJfbWQ1XzY0MDgyYiIgfiAiUmlzayBSZWR1Y3Rpb24gSW5kZXgiLAogICAgYmFuZCA9PSAibmF0dXJlX2FjY2Vzc19kaWZmX1NjM3YxX1BOVm5vYWctZXNhMjAyMCIgfiAiUGVvcGxlIHdpdGhpbiAxIGhvdXIiLAogICAgYmFuZCA9PSAibml0cm9nZW5fRVNBbW9kMi1TYzN2MV9tZDVfMDI0YTM2IiB+ICJOaXRyb2dlbiBFeHBvcnQgKGtnL2hhL3llYXIpIiwKICAgIGJhbmQgPT0gInBvbGxpbmF0aW9uX3BwbF9mZWRfb25fYWdfMTBzX1NjM3YxX1BOVm5vYWctZXNhMjAyMF9tZDVfNDA1Yzg4IiB+ICJQb2xsaW5hdGlvbiAoZXF1aXZhbGVudCBwZW9wbGUgZmVkKSIsCiAgICBiYW5kID09ICJwb2xsaW5hdGlvbl9wcGxfZmVkX29uX2hhYl9TYzN2MV9QTlZfbm9fYWctRVNBX21kNV81NzY3OTAiIH4gIlBvbGxpbmF0aW9uIChwZW9wbGUgZmVkIG9uIGhhYikiLAogICAgYmFuZCA9PSAic2VkaW1lbnRfRVNBbW9kMi1TYzN2MV9tZDVfMTQ5MDc4IiB+ICJTZWRpbWVudCBFeHBvcnQgKHRvbi9rZy95ZWFyKSIsCiAgICAjIC4uLiBhZGQgbW9yZSBjYXNlcyBmb3Igb3RoZXIgYmFuZHMgLi4uCiAgICBUUlVFIH4gYmFuZCAgIyBLZWVwIHRoZSBvcmlnaW5hbCBiYW5kIG5hbWUgaWYgbm8gbWF0Y2gKICApKQoKYWxsX3Jlc3VsdHMgPC0gYWxsX3Jlc3VsdHMgJT4lCiAgbXV0YXRlKGNvbG9yID0gY2FzZV93aGVuKAogICAgYmFuZCA9PSAiY3ZfaGFiaXRhdF92YWx1ZV9TYzN2MS1FU0Ftb2QyX3YyX21kNV82NDA4MmIiIH4gIiM3YTAxNzciLAogICAgYmFuZCA9PSAibmF0dXJlX2FjY2Vzc19kaWZmX1NjM3YxX1BOVm5vYWctZXNhMjAyMCIgfiAiI0E1N0MwMCIsCiAgICBiYW5kID09ICJuaXRyb2dlbl9FU0Ftb2QyLVNjM3YxX21kNV8wMjRhMzYiIH4gIiMyYzk0NGMiLAogICAgYmFuZCA9PSAicG9sbGluYXRpb25fcHBsX2ZlZF9vbl9hZ18xMHNfU2MzdjFfUE5Wbm9hZy1lc2EyMDIwX21kNV80MDVjODgiIH4gIiNkZDFjNzciLAogICAgYmFuZCA9PSAicG9sbGluYXRpb25fcHBsX2ZlZF9vbl9oYWJfU2MzdjFfUE5WX25vX2FnLUVTQV9tZDVfNTc2NzkwIiB+ICIjZGQxYjU2IiwKICAgIGJhbmQgPT0gInNlZGltZW50X0VTQW1vZDItU2MzdjFfbWQ1XzE0OTA3OCIgfiAiIzA4MzA2YiIsCiAgICAjIC4uLiBhZGQgbW9yZSBjYXNlcyBmb3Igb3RoZXIgYmFuZHMgLi4uCiAgICBUUlVFIH4gYmFuZCAgIyBLZWVwIHRoZSBvcmlnaW5hbCBiYW5kIG5hbWUgaWYgbm8gbWF0Y2gKICApKQoKc2F2ZShhbGxfcmVzdWx0cywgZmlsZT1oZXJlKCJJbnRlcnZlbnRpb25zIiwgIk1leF9pbnRlcnZlbnRpb24iLCAiYWxsX3Jlc3VsdHNfbXguUkRhdGEiKSkgCmBgYAoKIyMjIDQuMS4zIC4gUGxvdCBSZXN1bHRzIFl1Y2F0YW4gCgpgYGB7ciBwbG90IHl1Y2F0YW4sIGVjaG89RkFMU0V9CmxvYWQoZmlsZT1oZXJlKCJJbnRlcnZlbnRpb25zIiwgIk1leF9pbnRlcnZlbnRpb24iLCAiYWxsX3Jlc3VsdHNfbXguUkRhdGEiKSkKZGYgPC1hbGxfcmVzdWx0cyAlPiUgIGZpbHRlcihiYW5kIT0ibmF0dXJlX2FjY2Vzc19kaWZmX1NjM3YxX1BOVm5vYWctZXNhMjAyMCIpICU+JSBmaWx0ZXIoYmFuZCE9ICJwb2xsaW5hdGlvbl9wcGxfZmVkX29uX2hhYl9TYzN2MV9QTlZfbm9fYWctRVNBX21kNV81NzY3OTAiKQojIEFzc3VtaW5nIHlvdXIgJ2FsbF9yZXN1bHRzJyBkYXRhIGZyYW1lIGhhcyB0aGUgY29sdW1ucyAnU2VydmljZScsICd1bml0cycsIGFuZCAnY29sb3InCiMgQXNzdW1pbmcgeW91ciAnYWxsX3Jlc3VsdHMnIGRhdGEgZnJhbWUgaGFzIHRoZSBjb2x1bW5zICdTZXJ2aWNlJywgJ3VuaXRzJywgYW5kICdjb2xvcicKCiMgR2VuZXJhdGUgdGhlIGdncGxvdCBvYmplY3QKcGxvdCA8LSBnZ3Bsb3QoZGYsIGFlcyh5ID0gc3VtLCBmaWxsID0gY29sb3IpKSArCiAgZ2VvbV9ib3hwbG90KCkgKwogIGxhYnModGl0bGUgPSBzdHJfd3JhcCgiVG90YWwgZXN0aW1hdGVkIHNlcnZpY2UgY2hhbmdlIGluIHVuaXRzIGZvciB0aGUgdGFyZ2V0IGludGVydmVudGlvbiBhcmVhIC0gWXVjYXRhbiIsIHdpZHRoID0gNTApLCAKICAgICAgIHkgPSAiVG90YWwgU3VtIFZhbHVlIikgKwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKAogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksCiAgICBheGlzLnRpY2tzLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLAogICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKSwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiAgIyBSZW1vdmUgbGVnZW5kIHNpbmNlIGNvbG9yIGlzIGFscmVhZHkgbWFwcGVkCiAgKSArCiAgc2NhbGVfZmlsbF9pZGVudGl0eSgpICsgCiAgZmFjZXRfd3JhcCh+IFNlcnZpY2UsIHNjYWxlcyA9ICJmcmVlX3kiLCBsYWJlbGxlciA9IGxhYmVsbGVyKFNlcnZpY2UgPSBsYWJlbF93cmFwX2dlbih3aWR0aCA9IDEwKSkpICsgIAogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBmdW5jdGlvbih4KSB7CiAgICBpZiAobWF4KHgsIG5hLnJtID0gVFJVRSkgPiAxMDAwMDApIHsKICAgICAgcGFzdGUwKGZvcm1hdCh4IC8gMTAwMCwgYmlnLm1hcmsgPSAiLiIsIGRlY2ltYWwubWFyayA9ICIsIiksICJrIikKICAgIH0gZWxzZSB7CiAgICAgIGZvcm1hdCh4LCBiaWcubWFyayA9ICIuIiwgZGVjaW1hbC5tYXJrID0gIiwiKQogICAgfQogIH0pIApwcmludChwbG90KQpgYGAKCgojIE5leHQgU3RlcHM6CgpSdW4gdGhlIEFuYWx5c2lzIGZvciBNYWRyZSBkZSBEaW9zLCBpbmNvcnBwb3JhdGUgYmVuZWZpY2lhcmllcy9wb3B1bGF0aW9uIHJlbGF0ZWQgZGF0YSwgYXMgdGhlIHRhcmdldCBtZXRyaWMgaXMgbm90IHRoZSBzdW0gb2YgdGhlIHZhbHVlcy4KCg==